页面智能解析简介
简言之,页面的智能解析就是利用算法从页面的 HTML 代码中提取想要的内容,算法会自动计算出目标内容在代码中的位置并将它们提取出来。
实例引入
以一篇新闻的预览页面为例,如图 14-1 所示。 我们的需求是提取该页面中的标题、正 文、发布时间等。
想必大家可能见过,现在不少浏览器提供了阅读模式,例如我们用 Safari 浏览器打开示例新闻页面,然后开启阅读模式,效果将如图14-2所示。
图14-1 新闻的预览页面
图14-2 用阅读模式打开示例页面
可以看到页面变得非常清爽,只保留了标题和正文。原先页面中的导航栏、侧栏、评论等统统消失了。这是怎么做到的?难道提前针对这个页面写好提取规则了吗?当然不可能。其实是阅读模式内置了一些页面解析算法,可以自动抽出并呈现页面中的标题、正文等内容。
本节中,我们就来了解一下页面的智能解析相关的知识。
页面的智能解析
所谓页面的智能解析,就是不需要再专门写提取规则,而是利用算法直接计算页面中特定元素的位置和提取路径。针对我们的需求,可以通过算法计算出新闻标题是什么,正文应该在哪个区域,发布时间是什么时候。
其实智能解析操作起来非常难,人在看到网页上的一篇文章时,可以迅速找到它的标题、正文、发布时间、广告位、导航栏等。但把这篇文章放在机器面前,机器面对的仅仅是一系列HTML代码,怎么做到智能提取呢?其中融合了多方面的信息和规律。
-
标题:其字号一般比较大,长度通常介于1句话和2句话之间,位置一般在页面上方,且大多数时候和title节点单的内容一致。
-
正文:其内容一般最多,且包含多个p标签(段落)或者img标签(图片),宽度一般占页面的三分之二,文本密度(字数除以标签数量)比较大。
-
时间:不同语言的页面中显示的时间格式可能不同(如2021-02-20或者2021/02/20等,也可能是美式的记法),但格式的种类是有限的,可以通过特定的模式识别。
-
广告:其标签一般会带有ads字样,另外大多数广告会处于文章底部、页面侧栏,并包含一些特定的外链内容。
所以说,页面中的内容对应的节点是有一定特征的,包括节点位置、节点大小、节点标签、节点内容、节点文本密度等。智能提取除了利用这些特征,在很多情况下还需要借助视觉特征和文本特征,因此其中结合了算法计算、视觉处理、自然语言处理等多方面内容。把这些特征综合运用起来,再经过大量的数据训练,是可以得到一个非常不错的效果的。
业界进展
随着互联网的发展和信息的爆炸式增长,互联网上的页面会越来越多,页面的染方式也会发生很大的变化,智能解析能够大大减轻我们抽取信息的工作量。
其实,工业界已经有了落地的智能解析算法应用,例如 Diffbot、Embedly 等。目前,Diffbot 的提取效果算是比较领先的,其官方曾做过一个评测,使用不同的算法依次提取 Google 新闻上一些文章的标题和文本,然后与真实标注的内容做比较,比较指标就是文字的正确率和召回率,以及根据二者计算出的 F1 分数,结果如下。
-
正确率:0.968。
-
召回率:0.978。
-
F1:0.971。
我们可以发现,对于 Google 新闻的这些数据,Diffbot 大约能达到 97% 的正确率,效果还算不错。
Diffbot 是一家专门做网页智能提取的公司,提供了许多 API 来自动解析各种页面。其算法依赖于自然语言技术、机器学习、计算机视觉、标记检查等,并且所有页面都会考虑当前页面的样式以及可视化布局,还会分析其中包含的图像内容、CSS 甚至 Ajax 请求。在计算一个节点的置信度时,会考虑该节点和其他节点的关联关系,基于周围的标记来计算每个区块的置信度。总之,Diffbot 自 2010 年以来一直致力于提供这方面的服务,Diffbot 就是从页面解析起家的,现在也专注于页面解析服务,正确率高自然不足为怪了。
但 Diffbot 的算法并没有开源,只是以商业化 API 的形式售卖,我目前没有找到介绍其具体算法的论文。不过不妨碍这里拿它做案例,可以稍微体会一下智能解析算法能达到的效果。
Diffbot
打开Diffbot的官网(https://www.diffbot.com/),首先注册一个账号,会有15天的免费试用期,注册之后会获得一个DeveloperToken,这就是使用Diffbot接口服务的凭证。
接下来切换到测试页面(https://www.diftbot.com/dev/home/),测试一下Diffbot的解析效果。这里我们选择的测试页面就是本节开始所述的页面,填人页面链接,API类型选择“ArticleAPI”,然后点击“TestDrive”按钮,就会出现对测试页面进行解析的结果,如图14-3所示。
图14-3 解析测试页面的结果
可以看到,Diffbot帮我们提取了标题(title)、发布时间(date)、发布机构(author)、发布机构链接(authorUrl)和正文内容(text),而且目前来看都十分正确,发布时间也在自动识别之后做了转码,格式是标准的。
继续往下,看还有什么字段。可以看到html字段,和text字段不同的是,它包含文章内容的真实HTML代码,因此里面会包含图片,如图14-4所示。
图14-4文章内容的真实HTML代码
之后还有images字段,以列表形式返回了文章套图及每一张图的链接,另外还返回了文章的站点名称、页面所用语言等,如图14-5所示。
图14-5 其余返回结果
当然,我们也可以选择JSON格式的返回结果,其内容会更加丰富,例如图片的宽度、高度、图片描述,以及面包屑导航等,如图14-6所示。
图14-6JSON格式的返回结果
经过手工核对,发现其返回的结果完全正确,这说明正确率还是很高的。
所以,如果你对正确率的要求没有那么严苛,那么使用 Difrbot 可以快速提取页面中所需的结果,省去了绝大多数手工劳动,可以说非常赞。
另外,Diffbot 也提供了官方的 API 文档,如 AnalyzeAPI、ArticleAPI、Disscussion API 等。下面我们以 Article API 为例说明一下它的用法,其官方文档地址为 https://www.diffbot.com/dev/docs/article/ ,API 调用地址为 https://api.diffbot.com/v3/article 。
我们可以用 GET 方式请求这个 API,其必选参数有下面两个。
-
token:开发者的 Token。
-
url:要解析的 URL 链接。
可选参数有下面几个。
-
fields:用于指定返回哪些字段,默认已经有一些一定要返回的字段,还可以指定需要额外返回的字段。
-
paging:如果文章跨了多页,那么将这个参数设置为false可以禁止多页内容拼接。口maxTags:用于设置返回的Tag的最大数量,默认是10(单位为个)。
-
tagConfidence:用于设置置信度的阈值,置信度超过这个值的Tag才会被返回,默认是o.5。
-
discussion:将其值设置为false,代表不会解析评论内容。口timeout:解析时的最长等待时间,默认是3o(单位为秒)。口callback:为JSONP类型的请求设计的回调。
其中大家关注更多的应该是fields,这里我专门梳理了一下需要返回的字段,首先是一些一定要返回的字段。
-
type:文本类型,这里就是article。
-
title:文章的标题。
-
text:文章的纯文本内容,如果是分段内容,那么里面会以换行符分隔每一段。
-
html:提取结果的 HTML 内容。
-
date:文章的发布时间,格式为 RFC 1123。
-
estimatedDate:如果发布时间不太明确,就返回一个预估的时间:如果发布时间超过两天或者没有发布日期,就不返回这个字段。
-
author:文章的发布机构。
-
authorUrl:发布机构链接。
-
discussion:评论内容,和 Disscussion API 的返回结果一样。
-
humanLanguage:语言类型,如英文、中文等。
-
numPages:如果文章是多页的,那么这个参数会控制最大的翻页拼接数。
-
nextPages:如果文章是多页的,那么这个参数可以指定文章的后续链接。
-
siteName:站点名称。
-
publisherRegion:文章的发布地区。
-
publisherCountry:文章的发布国家。
-
pageUrl:文章的链接。
-
resolvedPageUrl:如果文章是从pageUrl重定向过来的,则返回此内容。
-
tags:文章的标签或者文章包含的实体,根据自然语言处理技术和DBpedia计算生成,是一个列表,里面又包含以下子字段。
-
label:标签名。
-
count:标签出现的次数。
-
score:标签置信度。
-
rdfTypes:如果实体可以由多个资源表示,那么返回相关的 URL。
-
type:标签类型。
-
uri:Diffbot Knowledge Graph 中的实体链接。
-
-
images:文章中包含的图片。
-
videos:文章中包含的视频。
-
breadcrumb:面包屑导航信息。
-
diffbotUri:Diffbot 内部的 URL 链接。
以上固定字段就是 “如果可以返回就一定会返回” 的字段,是不能定制的。我们也可以通过 fields 参数扩展如下可选字段。
-
quotes:引用信息。
-
sentiment:文章的情感值,取值在 -1 和 1 之间。
-
1inks:所有超链接的顶级链接。
-
querystring:请求的参数列表。
好,以上便是 Article API 的用法,大家可以在申请之后使用它做智能解析。下面用一个实例来看一下这个 API 的用法:
这里首先指定ArticleAPI的链接,然后指定了params参数,即GET请求的参数。参数中包含必选的token、url字段,以及可选的fields字段,fields字段的内容为meta标签。
运行结果如下:
如上返回内容以 JSON 格式呈现,包含文章的标题、正文、发布时间等内容。可见,不需要配置任何提取规则,我们就完成了页面的分析和爬取。
另外,Difibot 提供了几乎所有编程语言的 SDK 支持(详见 https://www.diftbot.com/dev/docs/libraries/ ),因此我们也可以使用 SDK 实现上述功能。如果使用的是Python语言,那么可以直接使用Python的 SDK一一DiffbotClient,链接为 https://github.com/diffbot/diffbot-python-client 。这个库并没有发布到 PyPi,需要自已下载并导人使用。此外,这个库是使用Python2编写的,本质上就是调用了requests库,大家感兴趣的话可以看一下。
下面是一个调用示例:
运行这段代码,就可以调用 ArticleAPI 来分析我们想要的URL链接了,返回结果跟前面的结果类似。
总结
本节介绍了智能解析的原理和 Diffbot 的用法。通过 Diffbot 的案例,我们大体了解了智能解析算法可以提取什么信息以及提取正确率如何。但 Diffbot 总归是一个商业化的 API,我们不能只知其然,不知其所以然。虽然很多时候只能靠调用商用 API 的方式智能解析页面,但一方面是费用高昂,另一方面是如果出了问题,没办法做针对性的处理和优化,我们显得非常被动。
如果我们能了解智能解析算法的核心原理和实现,很多问题就迎刃而解了。
之后几节我们会针对资讯类网站,介绍智能解析算法的一些原理和实现流程。对于大部分资讯类网站来说,除去一些特殊的页面(如登录页面、注册页面等),剩下的页面可以分为两大类——列表页和详情页,前者提供多个详情页的索引导航信息,后者则包含具体的内容。我们会针对这两类页面介绍如下知识点。
-
详情页中文章标题、正文、发布时间的提取算法和实现。
-
列表页中链接列表的提取算法和实现。
-
如何判断一个页面是详情页还是列表页。