Readability使用什么算法从URL中提取文本?

106

我曾经试图从一个URL中智能地提取“相关”的文本,消除与广告和其他杂乱无章的文本相关的信息。经过数月的研究,我发现这是一个无法准确确定的问题(我尝试过不同的方法,但都不可靠,因此放弃了)。

一周前,我偶然发现了Readability这个插件,可以将任何URL转换为易读的文本。我认为它看起来相当准确。我的猜测是,他们有一种算法可以智能地提取相关文本。

有人知道他们是如何做到的吗?或者我应该如何可靠地实现这一点?


3
问题是SO使用了什么算法,而Readability无法处理其页面? :) - Piotr Dobrogost
4个回答

182

易读性主要由一些启发式规则组成,在许多情况下它们“某种方式很好地工作”。

我写过一些关于这个主题的研究论文,并想解释一下为什么容易想出一个效果良好的解决方案以及何时接近100%准确度会变得困难的背景。

人类语言中似乎存在一条语言定律,这也(但不仅仅)表现在网页内容中,已经相当明显地将两种文本分开了(全文文本与非全文文本或大致上的“主要内容”与“底版”)。

从HTML中获取主要内容,在许多情况下只需保留HTML文本元素(即未被标记打断的文本块),这些文本块具有超过约10个单词。看起来人们从两种文本类型(通过它们发出的单词数衡量,“短”和“长”)中选择用于书写文本的两种不同动机。我将它们称为“导航”和“信息”动机。

如果作者希望您快速了解所写内容,则使用“导航”文本,即少量单词(如“STOP”、“Read this”、“Click here”)。这是导航元素(菜单等)中最突出的文本类型。

如果作者希望您深入理解他/她的意思,则使用更多单词。通过这种方式,消除了歧义,但增加了冗余。文章类内容通常属于此类,因为它不仅仅有几个单词。

虽然这种分离似乎在大量情况下有效,但在标题、短句、免责声明、版权脚注等方面变得棘手。

还有更为复杂的策略和特征可以帮助区分主要内容和样板内容。例如链接密度(块中包含链接的单词数与块中所有单词数之比)、前/后文块的特征、特定块文本在“整个”网络中的频率、HTML文档的DOM结构、页面的视觉形象等。

您可以阅读我的最新文章“使用浅层文本特征进行样板检测”,从理论角度获得一些见解。您也可以在VideoLectures.net上观看我的论文演示视频。

“可读性”算法使用了其中一些特征。如果您仔细观察SVN更新日志,就会发现算法的策略数量随时间而变化,提取质量也随之改善。例如,在2009年12月引入链接密度的策略非常有助于提高提取质量。

因此,在没有提到确切版本号的情况下说“可读性”算法是这样工作的是没有意义的。

我发布了一个名为boilerpipe的开源HTML内容提取库,提供了几种不同的提取策略。根据用例,某个提取器可能更有效。您可以使用Google AppEngine上的boilerpipe-web应用程序在自己选择的页面上尝试这些提取器。

为了让数字说话,可以查看boilerpipe维基上的“基准测试”页面,其中比较了一些提取策略,包括boilerpipe、Readability和苹果Safari。

我应该提到这些算法假设主要内容实际上是完整文本。但也有一些情况下,“主要内容”可能是其他东西,例如图像、表格、视频等。对于这些情况,算法效果不佳。


3
这个boilerpipe项目还在继续吗? - Abby
5
我建议您将项目上传至GitHub,这样可以吸引开源开发者的关注并推动社交化发展。 - Inanc Gumus
1
Kohlschütter博士解释的一个很好的例子实际上就是这个网页,在Safari浏览器中,如果您使用了Reader阅读模式,则会发现他的答案显示为主文本,这要归功于链接密度。与其他块相比,它是链接文本,因此被识别为主文本。 - Abdelrahman Eid
2
为了防止丢失,我将“迁移”了一份副本到我的repo https://github.com/k-bx/boilerpipe 中 :) - Konstantine Rybnikov

17

可读性是一个JavaScript书签小工具,意味着它是在客户端操作DOM的代码。查看JavaScript代码,你应该能够看到正在发生什么。

可读性的工作流程和代码:

/*
     *  1. Prep the document by removing script tags, css, etc.
     *  2. Build readability's DOM tree.
     *  3. Grab the article content from the current dom tree.
     *  4. Replace the current DOM tree with the new one.
     *  5. Read peacefully.
*/

javascript: (function () {
    readConvertLinksToFootnotes = false;
    readStyle = 'style-newspaper';
    readSize = 'size-medium';
    readMargin = 'margin-wide';
    _readability_script = document.createElement('script');
    _readability_script.type = 'text/javascript';
    _readability_script.src = 'http://lab.arc90.com/experiments/readability/js/readability.js?x=' + (Math.random());
    document.documentElement.appendChild(_readability_script);
    _readability_css = document.createElement('link');
    _readability_css.rel = 'stylesheet';
    _readability_css.href = 'http://lab.arc90.com/experiments/readability/css/readability.css';
    _readability_css.type = 'text/css';
    _readability_css.media = 'all';
    document.documentElement.appendChild(_readability_css);
    _readability_print_css = document.createElement('link');
    _readability_print_css.rel = 'stylesheet';
    _readability_print_css.href = 'http://lab.arc90.com/experiments/readability/css/readability-print.css';
    _readability_print_css.media = 'print';
    _readability_print_css.type = 'text/css';
    document.getElementsByTagName('head')[0].appendChild(_readability_print_css);
})();

如果你跟随上述代码引入的JS和CSS文件,你将获得整个图片:

http://lab.arc90.com/experiments/readability/js/readability.js(这是相当不错的注释,有趣的阅读)

http://lab.arc90.com/experiments/readability/css/readability.css


12

当然,没有100%可靠的方法来实现这一点。您可以在此阅读可读性源代码

基本上,他们正在尝试识别文本的积极消极块。正面标识符(即div IDs)可能是以下内容:

  • 文章
  • 正文
  • 内容
  • 博客
  • 故事

负面标识符可能是:

  • 评论
  • 讨论

然后他们有不太可能可能的候选人。 他们要做的是确定网站的主要内容最有可能是什么,参见可读性源代码中的第678行。这是通过分析段落的长度、它们的标识符(见上文)、DOM树(即如果段落是最后一个子节点)等来完成的,剥离所有不必要的内容,删除格式等。

代码共有1792行。这似乎是一个相当棘手的问题,因此您可以从中获得灵感。


2
你知道他们的代码是否是开源的,是否可以用于商业产品吗? - user300981
2
它表明源代码是根据Apache许可证2.0发布的,这意味着您可以使用它,分发它,修改并分发修改后的版本。但我对细节不是很清楚。 - slhck
2
@bobsmith 苹果在最新版本的Safari中使用了它。他们在发布说明中给予了Arc90的认可。 - s4y

8
有趣,我开发了一个类似的PHP脚本。它基本上会扫描文章并给所有文本加上词性标注(Brill标注器)。然后,语法无效的句子会立即被删除。接着,代词或过去时态的突然变化表明文章已结束或尚未开始。重复的短语会被搜索并消除,例如"Yahoo新闻体育财经"在页面中出现十次。你还可以通过各种情感相关的单词库获得关于语气的统计信息。从主动/消极/金融到被动/积极/政治的突然语气变化表示有边界。这是无穷无尽的,无论你想深挖多少都可以。
主要问题在于链接、嵌入式异常、脚本样式和更新。

3
听起来这确实是一个非常有趣的方法 - 你有没有相关的代码可以分享呢? - lsh
2
我同意,你有任何示例代码或关于你的代码的信息可以提供给我们参考吗? - userabuser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接