http://www.elias.cn/MyProject/ExtMainText
这是一个使用Python语言实现的函数库,能够帮助从html文档中提取文档正文,换句话说也就是能够过滤页面上的广告、栏目导航等非正文内容。此函数库可以用在从其他网站抓取文章内容的过程中,以及帮助搜索引擎抓取器忽略无关内容,将页面分析集中到网页更有价值的部分。
函数实现的基本原理是“正文标签密度法”,0.2版本计算网页每个html标签下的“正文长度/标签下所有字符总长”,取文档中密度高于制定阈值的最长部分作为文档正文输出。原理见:The Easy Way to Extract Useful Text from Arbitrary HTML。
对不同网站,因其语言特征及模板外观设计不同,而应当分别指定不同的密度阈值,具体应该根据所有标签的密度分布状况实验确定。一般英文网站可以取阈值0.5,中文网站使用0.5作为阈值同样能得到不错的输出结果。
- 当filterMode为 False 时,代码仅返回最长的一段正文,有可能会将博客的评论信息等过滤掉(当评论文字都比较短的时候);
- 当filterMode为 True 时,代码会过滤掉密度低于阈值的html片段,也即能够保留多段正文文字,从而通常可以保留博客的评论信息。
函数最终输出的是包含文档正文的html片段,如果需要将提取的正文内容进一步转换为text纯文本内容,则可以调用html2text。
English Doc, See: En.ExtMainText
2. 脚本下载
- 0.2a版本:Attach:ExtMainText_0.2a.zip
- 0.2版本:Attach:ExtMainText_0.2.zip
- 0.1a版本:Attach:ExtMainText_0.1a.zip
- 0.1版本:Attach:ExtMainText_0.1.zip
2.1 更新记录
- 2010-01-26:解决有时html文本中的特殊字符造成编码错误的问题。
- 2009-12-05:改为使用lxml api实现,使用新的密度计算公式,并增加“使用过滤模式”的选项。
- 2008-10-21:在__main__部分添加html向text转换的代码,直接执行ExtMainText将给出更直观的输出;作为0.1a版本发布。
- 2008-10-19:完成基本功能,作为0.1版本发布。
3. 使用说明
作为库函数使用时可参照源代码的DocString以及“ if __name__ == '__main__' ”部分。也可以直接运行此脚本文件:
这样脚本将以默认参数(0.5)提取该html文件的正文内容,并转换为纯文本输出。
另外请注意输入的html文本的编码,在0.2a之后的版本只接受unicode文本作为输入,因此需要提前完成对输入文档的解码。
4. 后续改进方向
相对于固定阈值,使用神经网络等智能方法能够获得更为准确的输出,建议参考也谈网页正文提取[下]以及赖勇浩先生翻译的从HTML文件中抽取正文的简单方案。
5. 与其他实现的比较
也谈网页正文提取[下]和The Easy Way to Extract Useful Text from Arbitrary HTML两篇文章的非人工智能算法的部分(也就是使用静态阈值方法来提取文章正文)在算法和代码实现上都是完全一样的。虽然都是使用文本密度来识别文章正文部分,但他们对文本密度的计算方法和我的还是存在一定区别,这里以我个人的理解进行简单的比较分析。
他们在计算文本密度时,从头至尾逐步解析html,当遇到一行纯文本内容时,以这一行纯文本的长度作为“文本长度”,以这一行纯文本结束位置到上一行纯文本结束位置在原始html中所跨越的字符总数作为“字符长度”,并用两者的比值作为文本密度的值。这种计算方法存在一定的不合理性。从物理意义上来讲,“字符长度”应该是与修饰一段纯文本相关的html代码总长。但他们的计算方法是将纯文本之前的html标签作为其修饰成分,对于前后匹配的html标签来说,特别是纯文本被括在多层表格及<div>标签之内的情况,不能保证将各层标签的结束标签算作此段纯文本的修饰内容,相反却很可能将之计算为下一行纯文本所对应的字节长度组成部分。在极端条件下,也即分析第一行纯文本时,算法会将之前的所有html标签算作字节组成部分,也即包含了<head>部分,这不合理地极大地降低了密度的取值。虽然扫描一般html页面遇到的第一行纯文本通常是菜单或者导航部分,需要作为正文提取的可能性不大,但这种算法实现方法与其预期体现的物理意义不能很好地吻合。
我的实现则将每个html标签下涵盖的所有内容作为整体来分析,比如对一个<div>标签,算法将此起始标签与其对应结束标签之间包括的所有纯文本内容作为“文本长度”,包括的所有字节内容作为“字节长度”,如此计算文本密度,可以保证所涉及的字节一定是与对应的纯文本密切相关的。因此对于静态阈值方法来说,估计能够获得稍好的正文提取准确度。
当然,那两篇文章的方法也有一定好处,就是对纯文本内容按照行来区分,对后续人工智能的训练和处理过程来说更便于人的操作和理解。但文中提及的神经网络方法并不是唯一的选择,或许可以不考虑文本行,而是从 html 标签的出现顺序上寻找规律。
6. 讨论
======================= 回帖========================
用如下这段html作了测试,发现s也被提了出来,建议楼主直接过滤掉head
<html><head><title>s</title></head><body>The Easy Way to Extract Useful Text from Arbitrary HTML<div>abcde123451234512345</div><div>12345abcde1</div></body></html>