知识图谱的很重要的原始数据来源还是来自于网站抓取的数据,网站抓取器就是我们常说的Spider。
在互联网上爬来爬去,发现链接,抓取网页,这就是Spider整天做的事情。听起来很简单,但是实际上是困难重重的。
Spider有两个核心任务:选链调度 和 网页抓取。
Spider面临的主要问题有:
最简单的抓取器就是一个实现了HTTP协议的客户端:接收一系列URL,向网站发起抓取,输出一系列网页。但是在实际中,简单的HTTP抓取不能完全满足抓取需求。除了高性能、高并发外,还有如下需求:
页面渲染功能的实现方案一把是基于chrome或者firefox内核实现,但有得必有失,这样会导致性能远差于简单的网页抓取器,并非所有网页都有这么复杂的渲染需求,可以让用户自己根据需要来选择。
另外,在这之前,还要能够保证不被网站封禁,比如控制抓取的频率、验证码破解、登录验证等。这些都是令人头疼的难题。
有了抓取器,给定一批链接,可以把网页抓回来。但从哪得到源源不断的链接以持续抓取呢?这就是新链拓展做的事情。
互联网拓朴是一个广泛连接的图,从一个小的核心网页集合出发(例如新浪,hao123),沿着链接可以找到互联网上绝大部分网页。新链拓展模块就是负责从网页上提取出新的链接。新提出的链接合并到老链接集合(原始链接称之为种子)中,从而使抓取可以持续,使爬虫的触角逐渐伸向全网,源源不断地得到新出现的网页链接。
通常情况下,链接是通过解析HTML树中的 <a>
标签得到的。但还有一些其它的提链方式:
另外,对于特定领域的抓取器,比如我们知识图谱,对于某个种子URL,拓展出来的新链是有要求的。例如从网易新闻的频道首页开始抓取,递归抓取(发现/拓展)新闻详情页。这一般通过正则表达式来描述新链拓展的规则。以上面的例子为例:
频道首页的URL格式为:http://news.163.com/domestic/,http://news.163.com/shehui/。所以其对应的正则表达式为:http://news.163.com/[a-z]*/。
新闻详情页的URL格式为:http://news.163.com/15/0630/16/ATCCTD9A00011229.html,http://news.163.com/15/0630/14/ATC89L110001124J.html。所以其对应的正则表达式为:http://news.163.com/[0-9] /[0-9] /[0-9] /. .html。
综上,如果我们想要创建一个全站抓取任务,从频道首页发现新闻详情页,则链接发现规则可以这样配:
入口页面正则:http://news.163.com/[a-z]*/
此入口页面允许的新链正则:http://news.163.com/[0-9] /[0-9] /[0-9] /. .html
那么解析器在分析频道首页时,发现的新链当中,符合新闻详情正则的链接都会被选取,放到种子库当中,供下轮调度使用。
页面解析器(抽取器)也只能针对某些pattern的URL进行页面抽取(通用的页面解析器,如新闻类型的一般准确率不高,很难满足抽取需求)。
可以持续抓取网页后,我们让这个系统自动跑下去。但是很快我们会发现链接和网页的数量迅速膨胀,简单的文件存储越来越慢,我们需要更高效的存储方式。怎么设计链接库和网页库的存储呢?
链接库的需求:
网页库的需求:
网页库数据量比较大,基本都是离线批量的读写应用(偏向于OLAP),所以业界通用做法是存放在HBase中。而对于链接库,则需要比较大量的随机大写,偏向于OLTP,所以DB(需要sharding)或者NoSQL(如ES)比较合适。
经过源源不断的 网页抓取=>新链扩展 周期循环之后,链接库里面的种子会非常多,但是抓取器每天能够抓取的链接是有限的,这就产生了一个问题:这么多链接究竟应该选哪些来抓取呢?这就是spider调度策略做的事情。
TIPS商业搜索引擎,spider的链接库里会有几千亿链接,但是每天发起抓取的链接量仅能够有几十亿。
1、广度有限
spider最原始、最基础的调度策略是广度优先。即:优先调度浅层链接。这里的深度并不是指URL的目录深度,而是链接从首页开始的follow深度(即常见的link_depth字段)。 这是符合一般人对网站的浏览习惯的。一般人从首页开始,通过导航链接,层层找到需要的内容。站长也会把一些重点推荐的内容或新内容放在首页或浅层栏目页上。而需要点击N多次才能发现的页面,一般用户很难找到,价值也不高。
2、链接分级
这个也是比较通用的做法,就是为每个种子分配权重(调度优先级),类似于操作系统的进程调度算法。
为了区分不同链接之间的优先级,spider选取时会对链接进行分级:
TIPS五种流量划分
我们希望每个站点上的链接可以按某种优先级排序。排好序后链接选取工作就极简单了,只要按顺序从高到低选即可。但我们发现并不是所有链接之间的优先级都是可比的。链接可以分成一些group,group内可比,group间不可比。
根据链接调度的需求,把链接分成五种流量类型:
这五种流量类型内部的链接优先级可直接比较,流量类型之间则不可比。流量类型之间的调度通过配比动态计算得到。
3、站点隔离选取
除了对链接根据流量类型进行group,为了体现站点之间的巨大差别,还可以考虑引入站点隔离选取机制。
在站点隔离选取机制下,linkbase按URL字典序(站点部分倒转)排列,相同站点的链接存储在一起。各个站点之间完全独立选取,方便各个站点进行独立的策略控制,避免了相互影响。
链接调度模型定下后,关键是如何更好更快地获取、计算链接相关各种属性,以及尽快地把这些属性生效到线上,影响调度。
spider调度的目标就是根据这些属性,安排出最优的调度顺序,使用最少的流量,获取最大的收益。
以前数据挖掘模块往往把最终调权的数据直接生成好,灌入link库。但这里面有很多拍脑袋的阈值和人工决策树。机器学习引入调度排序后,会越来越倾向于数据挖掘只产出基础属性,把基础属性回灌到link库中。基础属性怎么用,由机器学习来决定。
1、待抓链接调度
2、索引页调度
索引页的价值在于发现新链接。那么它的价值就要按follow出来的后链进行评价,可以用"母凭子贵"来概括。具体如何评价呢?
索引页分级主要由index-check模块完成。index-check模块根据link-pair产出的链接对信息,对索引页发现链接的能力进行评估,生成链接贡献度和强度谱数据。产出的索引页分级数据使用modlink回标到linkbase生效。
hubdig模块根据链接贡献度和强度谱数据进一步挖掘出hub页(高质量易变索引页)及hub页分级,以时效性CHK方式进行高频调度。
除此之外,通过pattern之间指向关系挖掘,也可以对索引页的分级产生影响。负责这项工作的模块叫link_uniq。 具体做法如下:
对于资源patternB,考察patternA对patternB的指向关系:patternA => patternB。定义四个衡量标准:
同时link-uniq还产出边框数据,作用于EC。用于辅助索引页识别(索引页识别主要看链接块面积,很重要的一点就是去除边框链接块的影响)。 边框的特点:
3、更新率调度
有大量存量的内容页,更新哪些呢?主要取决于两点:
具体排序策略:
选链调度是整个spider最复杂的模块,有很多深度挖掘、机器学习的东东在里面。