目前在做的项目中遇到一个需求:将爬取到的大量网页中的文本提取出来。由于网页太多,无法逐个分析使用xpath表达式进行提取。使用正则表达式可以实现,但太麻烦。这里介绍一款专业处理这方面问题的包w3lib

w3lib简介

​ w3lib是一个Python包,实现了一下与web相关的功能:

  • 从html片段中移除注释或者标签
  • 从html片段中提取base url
  • 对html串中的字符实体进行转义
  • 将原始HTTP头转换为字典格式
  • 构造HTTP的认证报头
  • 将html页面转换成unicode编码格式
  • 从urls中提取参数

​ w3lib主要包括四个模块:

  • html模块:处理与html标签相关的问题
  • http模块:处理与http报文相关的问题
  • url模块:处理与url地址相关的问题
  • encoding模块:处理与编码格式相关的问题

实例片段

​ w3lib是scrapy的依赖包,所有当我们安装好scrapy后不需额外安装w3lib。这里主要用到了html模块,关键代码段如下:

from w3lib.html import remove_tags
from w3lib.html import replace_entities

def get_text_from_divs(divs):
# input:body里面的所有div节点,每个div下还嵌套多层其他标签
# output:将每个div节点里除标签以外的文本提取出来,组成字符串
output = ""
for div in divs:
# 对每个div下的内容:
# 移除全部标签,转换全部字符实体,将所有转义字符(\n,\r,\t)替换成空格:
div_text = replace_escape_chars(replace_entities(remove_tags(div)), replace_by=" ")
# div_text由当前div下嵌套的其他标签之间的文本组成,这些文本之间存在大量重复空格
# 将重复空格替换成一个空格:
content = " ".join(div_text.split())
# 将每个div中的文本拼接成字符串,用空格间隔
output = output + content + " "
return output

def parse(self, response):
divs = response.xpath("//body/div").extract()
content = utils.get_text_from_divs(divs)
print(content)

函数功能

​ 这里主要使用了html模块下的三个函数
remove_tags() 默认情况下移除所有html标记,及标签的属性,只保留标签之间的文本,实例如下:

>>> import w3lib.html
>>> doc = '<div><p><b>This is a link:</b> <a href="http://www.example.com">example</a></p></div>'
>>> w3lib.html.remove_tags(doc)
'This is a link: example'

replace_entities()主要用于移除文本之间的字符实体,比如&nbsp>

replace_escape_chars()主要用于移除文本之间的专业字符,包括\n\r、`\t