目前在做的项目中遇到一个需求:将爬取到的大量网页中的文本提取出来。由于网页太多,无法逐个分析使用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_entitiesdef 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 outputdef 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()
主要用于移除文本之间的字符实体,比如 
、>
等
replace_escape_chars()
主要用于移除文本之间的专业字符,包括\n
、\r
、\t