Posted on:
Last modified:
Readability 是一个可以从杂乱无章的网页中抽取出无特殊格式,适合再次排版阅读的文章的库。比如,我们常见的手机浏览器的阅读模式很大程度上就是采用的这个库,还有 evernote 的 webclipper 之类的应用也都是利用了类似的库。Readability 的各个版本都源自 arc90 的 readability.js 这个库,之前尝试阅读过 js 版本,无关的辅助函数太多了,而且 js 的 dom api 实在称不上优雅,读起来晦涩难通,星期天终于有时间拜读了一下 python-readability 的代码。
readability 核心是一个 Document 类,这个类代表了一个 HTML 文件,同时可以输出一个格式化的文件。
Readability 目录下的文件:
readability
├── __init__.py
├── browser.py
├── cleaners.py
├── debug.py
├── encoding.py
├── htmls.py
└── readability.py
核心的是 readability.py 文件。其他的都可以理解为辅助类。
下面介绍 Document 中的方法。
summary 方法是核心方法,可以抽取出一篇文章,可能需要对文章抽取多次才能获得符合条件的文章。这个方法的核心思想是:
remove_unlikely_candidates
去掉不太可能的候选transform_misused_divs_into_ps
把错误使用的 div 转换成 p 标签,这样就不用考虑 div 标签了,其实这步挺关键的。其实还有一些其他的处理需要使用。强力模式和非强力模式的关键区别在于是否调用了 remove_unlikely_candidates
对于以上的核心步骤,已经足够应付大多数比较规范的网页。但是还是会有不少识别错误。公司内部的改进做法在于:
此处省略 1000 个字。
下面按照在 summary 出场顺序依次介绍~
匹配标签的 class 和 id,根据 unlikelyCandidatesRe 和 okMaybeItsACandidate 这个两个表达式删除一部分节点。
unlikelyCandidatesRe:combx|comment|community|disqus|extra|... 可以看出是一些边缘性的词汇
okMaybeItsACandidateRe: and|article|body|column|main|shadow... 可以看出主要是制定正文的词汇
注意:
就是 ordered 中找出最大的
对于最佳候选周围的标签,给予复活的机会,以避免被广告分开的部分被去掉,阈值是 10 分或者最佳候选分数的五分之一。如果是 p 的话,node_length > 80
and link_density < 0.25
或者 长度小于 80,但是没有连接,而且最后是句号
readability 之所以能够 work 的原因,很大程度上是基于 html 本身是一篇文档,数据都已将在 html 里了,然后通过操作 DOM 获得文章。而在前端框架飞速发展的今天,随着 react 和 vue 等的崛起,越来越多的网站采用了动态加载,真正的文章存在了页面的 js 中甚至需要 ajax 加载,这时在浏览器中使用 readability.js 虽然依然可以(因为浏览器已经加载出了 DOM),但是如果用于抓取目的的话,需要执行一遍 js,得到渲染过的 DOM 才能提取文章,如果能够有一个算法,直接识别出大段的文字,而不是依赖 DOM 提取文章就好了~
除去 Readability 之外,还有一些其他的文章抽取工具,都调研了一下:
readability
goose3,性能不好。而且只支持中文、英文、阿拉伯语和汉语。
newspaper,非常不好使,什么也抽不出来
textract,从各种文件中抽取文字,可以作为没有特定抽取器时的 baseline.
html2text,Arron 的遗作,还好有 Python3 移植。这个并不能抽取正文,只是转换成 markdown,不过从转换出来的 Markdown 似乎很好找出正文。
网上还有一些按照文本密度抽取的想法,实在是考虑得太少了,基本属于想当然。
除了 buriy/python-readability
之外,另外两个值得参考的实现是:bookieio/breadability
和 mozilla/readability
。前者有一些测试用例值得参考,后者有最新的 js 实现。
© 2016-2022 Yifei Kong. Powered by ynotes
All contents are under the CC-BY-NC-SA license, if not otherwise specified.
Opinions expressed here are solely my own and do not express the views or opinions of my employer.
友情链接: MySQL 教程站