抓取学习笔记

知识图谱的很重要的原始数据来源还是来自于网站抓取的数据,网站抓取器就是我们常说的Spider。


在互联网上爬来爬去,发现链接,抓取网页,这就是Spider整天做的事情。听起来很简单,但是实际上是困难重重的。


Spider有两个核心任务:选链调度 和 网页抓取。


Spider面临的主要问题有:


  • 压力计算、控制、流量分配:

    • 如何提升对外抓取友好度,减少被封禁。如何评估网站可承受的压力。如何在多用户之间,多种不同的抓取需求之间进行流量分配。

  • 抓取流量有限,需要根据预测合理调度,使收益最大化:

    • 链接发现:需要预测优先CHK哪些页面可能发现更多更好的新链接。

    • 待抓分级:需要在抓取之前预测哪些待抓链接对应的网页质量更高,从而优先抓取。

    • 页面更新:需要预测哪些网页更可能发生了变化(或失效),哪些网页的变化更重要,从而优先CHK。

    • 这些预测通常需要基于对现有数据的挖掘统计,由已抓反馈待抓,由历史调度推测未来调度。在这个过程中会用到大规模数据挖掘,机器学习等方法。

  • 收录控制:互联网上有大量各种重复、垃圾信息,如果不加限制,我们的系统将很快被垃圾占领。需要判断网页的质量,挖掘网页的重复规律,在尽可能早的地方把垃圾和重复控制住。

1、抓取器(Crawler)


最简单的抓取器就是一个实现了HTTP协议的客户端:接收一系列URL,向网站发起抓取,输出一系列网页。但是在实际中,简单的HTTP抓取不能完全满足抓取需求。除了高性能、高并发外,还有如下需求:


  • 多抓取协议支持:目前主要是HTTP和HTTPS。

  • 多种资源类型:多文档、图片、视频。

  • 页面拼接:对内嵌frame页进行抓取拼接。

  • 页面跳转:跳转可以通过HTTP头、HTML meta标签静态实现,也可以通过javascript动态实现。前者容易识别,后者依赖javascript解析,很难精确做到。

  • 页面渲染:像浏览器一样执行javascript代码和css渲染,使输出网页看起来像在浏览器里看到的一样。

页面渲染功能的实现方案一把是基于chrome或者firefox内核实现,但有得必有失,这样会导致性能远差于简单的网页抓取器,并非所有网页都有这么复杂的渲染需求,可以让用户自己根据需要来选择。


另外,在这之前,还要能够保证不被网站封禁,比如控制抓取的频率、验证码破解、登录验证等。这些都是令人头疼的难题。


2、新链拓展


有了抓取器,给定一批链接,可以把网页抓回来。但从哪得到源源不断的链接以持续抓取呢?这就是新链拓展做的事情。


互联网拓朴是一个广泛连接的图,从一个小的核心网页集合出发(例如新浪,hao123),沿着链接可以找到互联网上绝大部分网页。新链拓展模块就是负责从网页上提取出新的链接。新提出的链接合并到老链接集合(原始链接称之为种子)中,从而使抓取可以持续,使爬虫的触角逐渐伸向全网,源源不断地得到新出现的网页链接。


通常情况下,链接是通过解析HTML树中的<a>标签得到的。但还有一些其它的提链方式:


  • 链接可能直接以纯文本的形式出现。需要抽取器从文本中正确地截取链接部分。

  • 链接可能由javascript脚本动态生成,甚至需要用户点击操作才能触发生成。这时候需要借助有页面渲染能力的抓取器来解决提链问题了。

另外,对于特定领域的抓取器,比如我们知识图谱,对于某个种子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进行页面抽取(通用的页面解析器,如新闻类型的一般准确率不高,很难满足抽取需求)。


3、链接库与网页库


可以持续抓取网页后,我们让这个系统自动跑下去。但是很快我们会发现链接和网页的数量迅速膨胀,简单的文件存储越来越慢,我们需要更高效的存储方式。怎么设计链接库和网页库的存储呢?


链接库的需求:


  • schema支持(定长、变长字段都有)

  • 批量读需求(选取链接)

  • 批量写需求(把新链接合并回链接库)

  • 随机读需求(小量)

  • 记录长度较小,差异不大(平均几百Byte,最大1KB以内)

  • 有大量read-modify-write需求(链接状态的改变需要参考上次的链接状态)

网页库的需求:


  • schema支持(定长、变长字段都有)

  • 批量读需求(建索引库)

  • 批量写需求(spider抓回来的网页入网页库)

  • 随机读需求(小量)

  • 记录长度较大,差异较大(平均几十KB,最大达到几MB级)

网页库数据量比较大,基本都是离线批量的读写应用(偏向于OLAP),所以业界通用做法是存放在HBase中。而对于链接库,则需要比较大量的随机大写,偏向于OLTP,所以DB(需要sharding)或者NoSQL(如ES)比较合适。


4、选链调度


经过源源不断的 网页抓取=>新链扩展 周期循环之后,链接库里面的种子会非常多,但是抓取器每天能够抓取的链接是有限的,这就产生了一个问题:这么多链接究竟应该选哪些来抓取呢?这就是spider调度策略做的事情。


TIPS 商业搜索引擎,spider的链接库里会有几千亿链接,但是每天发起抓取的链接量仅能够有几十亿。


调度策略模型


1、广度有限


spider最原始、最基础的调度策略是广度优先。即:优先调度浅层链接。这里的深度并不是指URL的目录深度,而是链接从首页开始的follow深度(即常见的link_depth字段)。 这是符合一般人对网站的浏览习惯的。一般人从首页开始,通过导航链接,层层找到需要的内容。站长也会把一些重点推荐的内容或新内容放在首页或浅层栏目页上。而需要点击N多次才能发现的页面,一般用户很难找到,价值也不高。


2、链接分级


这个也是比较通用的做法,就是为每个种子分配权重(调度优先级),类似于操作系统的进程调度算法。


为了区分不同链接之间的优先级,spider选取时会对链接进行分级:


  • 先根据链接属性计算出权重

  • 再根据权重映射到级别

  • 选取时从高级别向低级别选取

  • 低级别有低保,保证不会被饿死

  • 同级别内随机选取

TIPS 五种流量划分


我们希望每个站点上的链接可以按某种优先级排序。排好序后链接选取工作就极简单了,只要按顺序从高到低选即可。但我们发现并不是所有链接之间的优先级都是可比的。链接可以分成一些group,group内可比,group间不可比。


根据链接调度的需求,把链接分成五种流量类型:


  • 覆盖率CHK

  • 覆盖率GET

  • 时效性CHK

  • 时效性GET

  • 更新率CHK

这五种流量类型内部的链接优先级可直接比较,流量类型之间则不可比。流量类型之间的调度通过配比动态计算得到。


3、站点隔离选取


除了对链接根据流量类型进行group,为了体现站点之间的巨大差别,还可以考虑引入站点隔离选取机制。


在站点隔离选取机制下,linkbase按URL字典序(站点部分倒转)排列,相同站点的链接存储在一起。各个站点之间完全独立选取,方便各个站点进行独立的策略控制,避免了相互影响。


调度依赖的属性


链接调度模型定下后,关键是如何更好更快地获取、计算链接相关各种属性,以及尽快地把这些属性生效到线上,影响调度。


待抓链接可以拿到的属性


  • URL长相:有很多文章可以做。

    • domain

    • stat-pattern

    • keyman-pattern

    • domain+anchor聚类

    • 各种聚类:聚类后已抓链接的各种属性统计后都可以反馈到待抓

    • 首页/dir_depth,链接长度

    • 从URL上提取时间

  • 反链/anchor/fresh-pp/page_rank/微博转发

    • anchor-mine:根据anchor挖掘,对linkbase进行操作,对链接进行提权或降权。

  • 前链/link_depth/hub_depth

  • sobar访问

  • 推送链接的meta信息

已抓链接可以拿到的属性


  • 所有待抓链接的属性

  • 抓取反馈

    • 抓取状态:成功/失败,返回码

  • 单页面级特征

    • 页面价值:质量(有效性、丰富度、整洁度),受众

    • 页面类型:索引页/内容页,语义分类:新闻/小说/视频/博客…

    • 页面提取信息:正文、标题、链接、页面发布时间、结构化数据

  • 多页面特征

    • 页面价值:稀缺(重复度)

    • 贡献新链接能力

  • 时间维度特征

    • 抓取历史记录

    • 易变性/易死性

  • 建库反馈

    • 建库级别:vip/se/大度/时效性…

  • 线上反馈

    • 点击、展现

spider调度的目标就是根据这些属性,安排出最优的调度顺序,使用最少的流量,获取最大的收益。


以前数据挖掘模块往往把最终调权的数据直接生成好,灌入link库。但这里面有很多拍脑袋的阈值和人工决策树。机器学习引入调度排序后,会越来越倾向于数据挖掘只产出基础属性,把基础属性回灌到link库中。基础属性怎么用,由机器学习来决定。


一些重要的调度策略


1、待抓链接调度


  • 思路:使用机器学习的方法,根据待抓链接的属性,学习抓取后的页面价值。

  • 难点:

    • 反链、anchor、page_rank等需要反转和迭代的比较难做。架构需要考虑如何更好地支持。

    • 不要太粗:区分度不够

    • 不要太细:样本数太少

    • 高内聚:对于待预测目标属性,聚类产生的粒度要高内聚。即:聚在一起的链接的目标属性应该接近。

    • 低耦合:不同的聚类之间,目标属性应该有区分度。

    • 已抓反馈待抓,选择合适的粒度

    • 提升各种属性的反馈速度

2、索引页调度


索引页的价值在于发现新链接。那么它的价值就要按follow出来的后链进行评价,可以用”母凭子贵”来概括。具体如何评价呢?


  • 人无我有

    • 别人follow不出来的链接,我能follow出来。

  • 人有我精

    • 别人follow出来的链接质量平平,我follow出来的都是优质链接。

  • 人精我快

    • 大家都能follow出来的链接,我比别人抢先一步。

索引页分级主要由index-check模块完成。index-check模块根据link-pair产出的链接对信息,对索引页发现链接的能力进行评估,生成链接贡献度和强度谱数据。产出的索引页分级数据使用modlink回标到linkbase生效。


hubdig模块根据链接贡献度和强度谱数据进一步挖掘出hub页(高质量易变索引页)及hub页分级,以时效性CHK方式进行高频调度。


除此之外,通过pattern之间指向关系挖掘,也可以对索引页的分级产生影响。负责这项工作的模块叫link_uniq。 具体做法如下:


对于资源patternB,考察patternA对patternB的指向关系:patternA => patternB。定义四个衡量标准:


  • uniq度:指向关系中patternB链接集合uniq后数量 / 指向关系对总量

    • 衡量指向关系的重复程度。如果重复度高,意味着调度patternA的链接follow出patternB的链接大部分都是老链接。

  • 覆盖度:指向关系中patternB链接集合uniq后数量 / patternB收录链接总量

    • 衡量通过对patternA中链接的调度,可以发现patternB中多大比例的链接。

  • 贡献度:指向关系中patternB链接集合uniq后数量 / 指向关系中patternA链接集合uniq后数量

    • 衡量对patternA中链接的调度能否起到”四两拨千斤“的效果。

  • 有效度:指向关系中patternA链接集合uniq后数量 / patternA收录链接总量

    • 衡量此挖掘结果对于patternA是否具有统计意义。如果patternA中仅有少量链接follow出patternB,那反馈到全体patternA链接就是错误的。 link-uniq产出低价值指向数据,作用于effect,对中级别索引页进行降权。提升中级别索引页CHK有效性。

同时link-uniq还产出边框数据,作用于EC。用于辅助索引页识别(索引页识别主要看链接块面积,很重要的一点就是去除边框链接块的影响)。 边框的特点:


  • 同功能页面上,边框处于相同位置。边框对应的后链往往重复度很高,即uniq度很低。可以通过这种方式挖掘出每种pattern上的边框块。 但link-uniq挖掘非常耗时,历史上挖掘次数很少,因此产生的效果也不大。如何降低这种大型数据挖掘的成本,使之常态化运行,也是架构方需要考虑的重要问题。

3、更新率调度

有大量存量的内容页,更新哪些呢?主要取决于两点:

变化的概率:变好变差变化
    • 网页特性本身的易变性:不同网页易变性不同。商品信息页,BBS页

    • 已CHK反馈待CHK:同类链接大量变化,可能意味着该链接也有变化

  • 更新的收益:

    • 是否在索引库,在哪个库中?

    • 是否有点击、展现等

    • 如果不在索引中,或者没有点击展现,那么即使不更新,影响也较小

具体排序策略:

  • 更新概率模型

    • 定期pattern聚类挖掘网页变化情况

    • 网页自身属性

    • 集合反馈属性

    • 机器学习:由以上属性计算出网页变化概率

  • 更新收益计算

    • 建库反馈网页在什么索引库中

    • 检索端点击、展现反馈

    • 不同收益给予不同权重

  • 综合计算CHK收益

    • 用(更新概率 * 更新收益)衡量CHK某链接的优先级

选链调度是整个spider最复杂的模块,有很多深度挖掘、机器学习的东东在里面。

作者介绍



郑志彬,华南理工大学计算机科学与技术(双语班)。先后在BAT从事过电子商务、开放平台、移动浏览器、搜索广告后台和大数据人工智能等相关开发和架构。擅长各种业务形态的业务架构、平台化以及各种业务解决方案。


百度众包-全国最大的众包服务平台,提供一站式海量数据训练服务,包括数据获取,数据加工,以及数据的定制化服务,实现数据价值最大化。




大咖招募
欢迎App研发/测试方面的大牛来投稿,开设专栏。我们提供丰厚的稿酬,预约个人专访,帮助建立个人技术品牌!
立即投稿

我要评论

字数不能超过140字,谢谢!
提交

评论({{allComments.length}})

{{comment.create_time.substr(0,16)}}

显示所有评论
你好,请问有什么可以帮助您?
咨询客服