5 04 | 网页爬虫设计:如何下载千亿级网页?

Posted 程序杰杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5 04 | 网页爬虫设计:如何下载千亿级网页?相关的知识,希望对你有一定的参考价值。

你好,我是李智慧。

在互联网早期,网络爬虫仅仅应用在搜索引擎中。随着大数据时代的到来,数据存储和计算越来越廉价和高效,越来越多的企业开始利用网络爬虫来获取外部数据。例如:获取政府公开数据以进行统计分析;获取公开资讯以进行舆情和热点追踪;获取竞争对手数据以进行产品和营销优化等等。

网络爬虫有时候也被称为网络机器人,或者网络蜘蛛。我们准备开发一个全网爬虫,爬取全(中文)互联网的公开网页,以构建搜索引擎和进行数据分析。爬虫名称为“Bajie(八戒)”。

Bajie的技术挑战包括:如何不重复地获取并存储全网海量URL?如何保证爬虫可以快速爬取全网网页但又不会给目标网站带来巨大的并发压力?接下来我们就来看看Bajie的需求与技术架构。

需求分析

Bajie的功能比较简单,这里不再赘述。

性能指标估算

因为互联网网页会不断产生,所以全网爬虫Bajie也是一个持续运行的系统。根据设计目标,Bajie需要每个月从互联网爬取的网页数为20亿个,平均每个页面500KB,且网页需存储20年。

Bajie的存储量和TPS(系统吞吐量)估算如下。

  • 每月新增存储量
    估计平均每个页面500KB,那么每个月需要新增存储1PB。

$small 20亿times500KB=1PB$

  • 总存储空间
    网页存储有效期20年,那么需要总存储空间240PB。

$small 1PBtimes12个月times20年=240PB$

  • TPS
    Bajie的TPS应为800。

$small 20亿div(30times24times60times60)approx800$

非功能需求

Bajie需要满足的非功能需求如下。

  1. 伸缩性:当未来需要增加每月爬取的网页数时,Bajie可以灵活部署,扩大集群规模,增强其爬取网页的速度。也就是说,Bajie必须是一个分布式爬虫。
  2. 健壮性:互联网是一个开放的世界,也是一个混乱的世界,服务器可能会宕机,网站可能失去响应,网页HTML可能是错误的,链接可能有陷阱……所以Bajie应该能够面对各种异常,正常运行。
  3. 去重:一方面需要对超链接URL去重,相同的URL不需要重复下载;另一方面还要对内容去重,不同URL但是相同内容的页面也不需要重复存储。
  4. 扩展性:当前只需要爬取HTML页面即可,将来可能会扩展到图片、视频、文档等内容页面。
    此外,Bajie必须是“礼貌的”。爬虫爬取页面,实际上就是对目标服务器的一次访问,如果高并发地进行访问,可能会对目标服务器造成比较大的负载压力,甚至会被目标服务器判定为DoS攻击。因此Bajie要避免对同一个域名进行并发爬取,还要根据目标服务器的承载能力增加访问延迟,即在两次爬取访问之间,增加等待时间。

并且,Bajie还需要遵循互联网爬虫协议,即目标网站的robots.txt协议,不爬取目标网站禁止爬取的内容。比如www.zhihu.com的robots.txt内容片段如下。

User-agent: bingbot
Disallow: /appview/
Disallow: /login
Disallow: /logout
Disallow: /resetpassword
Disallow: /terms
Disallow: /search
Allow: /search-special
Disallow: /notifications
Disallow: /settings
Disallow: /inbox
Disallow: /admin_inbox
Disallow: /*?guide*

Zhihu约定Bing爬虫可以访问和不可以访问的路径都列在robots.txt中,其他的Google爬虫等也在robots.txt中列明。
robots.txt还可以直接禁止某个爬虫,比如淘宝就禁止了百度爬虫,淘宝的robots.txt如下。

User-agent: Baiduspider
Disallow: /
User-agent: baiduspider
Disallow: /

淘宝禁止百度爬虫访问根目录,也就是禁止百度爬取该网站所有页面。
robots.txt在域名根目录下,如www.taobao.com/robots.txt。Bajie应该首先获取目标网站的robots.txt,根据爬虫协议构建要爬取的URL超链接列表。

概要设计

Bajie的设计目标是爬取数千亿的互联网页,那么Bajie首先需要得到这千亿级网页的URL,该如何获得呢?

全世界的互联网页面事实上是一个通过超链接连接的巨大网络,其中每个页面都包含一些指向其他页面的URL链接,这些有指向的链接将全部网页构成一个有向(网络)图。如下图所示,每个节点是一个网页,每条有向的边就是一个超链接。

上图中,www.a.com包含两个超链接,分别是www.b.com和www.c.com,对应图中就是节点www.a.com指向节点www.b.com和节点www.c.com的边。同样地,www.b.com节点也会指向www.d.com节点。

如果我们从这个图中的某个节点开始遍历,根据节点中包含的链接再遍历其指向的节点,再从这些新节点遍历其指向的节点,如此下去,理论上可以遍历互联网上的全部网页。而将遍历到的网页下载保存起来,就是爬虫的主要工作。

所以,Bajie不需要事先知道数千亿的URL,然后再去下载。Bajie只需要知道一小部分URL,也就是所谓的种子URL,然后从这些种子URL开始遍历,就可以得到全世界的URL,并下载全世界的网页。

Bajie的处理流程活动图如下。

首先Bajie需要构建种子URL,它们就是遍历整个互联网页面有向图的起点。种子URL将影响遍历的范围和效率,所以我们通常选择比较知名的网站的主要页面(比如首页)作为种子URL。

然后,URL调度器从种子URL中选择一些URL进行处理。后面将在详细介绍中说明URL调度器的算法原理。

Bajie对选择出来的URL经过域名解析后,下载得到HTML页面内容,进而解析HTML页面,分析该内容是否已经在爬虫系统中存在。因为在互联网世界中,大约有三分之一的内容是重复的,下载重复的内容就是在浪费计算和存储资源。如果内容已存在,就丢弃该重复内容,继续从URL调度器获取URL;如果不存在,就将该HTML页面写入HDFS存储系统。

然后,Bajie进一步从已存储的HTML中提取其内部包含的超链接URL,分析这些URL是否满足过滤条件,即判断URL是否在黑名单中,以及URL指向的目标文件类型是否是爬虫要爬取的类型。

如果HTML中的某些URL满足过滤条件,那么就丢弃这些URL;如果不满足过滤条件,那么,进一步判断这些URL是否已经存在,如果已经存在,就丢弃该URL,如果不存在,就记录到待下载URL集合。URL调度器从待下载URL集合中选择一批URL继续上面的处理过程。

这里需要注意,想判断URL是否已经存在,就要判断这个URL是否已经在待下载URL集合中。此外,还需要判断这个URL是否已经下载得到HTML内容了。只有既不是待下载,也没被下载过的URL才会被写入待下载URL集合。

可以看到,在爬虫的活动图里是没有结束点的,从开始启动,就不停地下载互联网的页面,永不停息。其中,URL调度器是整个爬虫系统的中枢和核心,也是整个爬虫的驱动器。爬虫就是靠着URL调度器源源不断地选择URL,然后有节奏、可控地下载了整个互联网,所以URL调度器也是爬虫的策略中心

据此,Bajie的部署图如下。

Bajie系统中主要有两类服务器,一类是URL调度器服务器;一类是URL下载处理服务器集群,它是一个分布式集群。

URL调度器从种子URL或待下载URL集合中载入URL,再根据调度算法,选择一批URL发送给URL下载处理服务器集群。这个下载处理服务器集群是由多台服务器组成的,根据需要达到的TPS,集群规模可以进行动态伸缩,以实现需求中的伸缩性要求。

每台URL下载处理服务器先得到分配给自己的一组URL,再启动多个线程,其中每个线程处理一个URL,按照前面的流程,调用域名解析组件、HTML下载组件、HTML内容解析组件、内容去重组件、URL提取组件、URL过滤组件、URL去重组件,最终将HTML内容写入HDFS,并将待下载URL写入待下载URL集合文件。

分布式爬虫

需要注意的是,URL下载处理服务器采用分布式集群部署,主要是为了提高系统的吞吐能力,使系统满足伸缩性需求。而URL调度器则只需要采用一台高性能的服务器单机部署即可。

事实上,单机URL调度器也完全能够满足目前800TPS的负载压力,以及将来的伸缩要求。因为800TPS对于URL调度器而言其实就是每秒产生800个URL而已,计算压力并不大,单台服务器完全能够满足。

同时URL调度器也不需要考虑单服务器宕机导致的可用性问题,因为爬虫并不是一个实时在线系统,如果URL调度器宕机,只需要重新启动即可,并不需要多机部署高可用集群。

相对应地,每个URL在URL下载处理服务器上的计算负载压力要大得多,需要分布式集群处理,也因此大规模爬虫被称为分布式爬虫,Bajie就是一个分布式爬虫。

详细设计

Bajie详细设计关注3个技术关键点:URL调度器算法、去重算法、高可用设计。

URL调度器算法

URL调度器需要从待下载URL集合中选取一部分URL进行排序,然后分发给URL下载服务器去下载。待下载URL集合中的URL是从下载的HTML页面里提取出来,然后进行过滤、去重得到的。一个HTML页面通常包含多个URL,每个URL又对应一个页面,因此,URL集合数量会随着页面不断下载而指数级增加。

待下载URL数量将远远大于系统的下载能力,URL调度器就需要决定当前先下载哪些URL

如果调度器一段时间内选择的都是同一个域名的URL,那就意味着我们的爬虫将以800 TPS的高并发访问同一个网站。目标网站可能会把爬虫判定为DoS攻击,从而拒绝请求;更严重的是,高并发的访问压力可能导致目标网站负载过高,系统崩溃。这样的爬虫是“不礼貌”的,也不是Bajie的设计目标。

前面说过,网页之间的链接关系构成一个有向图,因此我们可以按照图的遍历算法选择URL。图的遍历算法有深度优先和广度优先两种,深度优先就是从一个URL开始,访问网页后,从里面提取第一个URL,然后再访问该URL的页面,再提取第一个URL,如此不断深入。

深度优先需要维护较为复杂的数据结构,而且太深的下载深度导致下载的页面非常分散,不利于我们构建搜索引擎和数据分析。所以我们没有使用深度优先算法。

那广度优先算法如何呢?广度优先就是从一个URL开始,访问网页后,从中得到N个URL,然后顺序访问这个N个URL的页面,然后再从这N个页面中提取URL,如此不断深入。显然,广度优先实现更加简单,获取的页面也比较有关联性。

图的广度优先算法通常采用队列来实现。首先,URL调度器从队列头出队列(dequeue)取一个URL,交给URL下载服务器,下载得到HTML,再从HTML中提取得到若干个URL入队列(enqueue)到队列尾,URL调度器再从队列头出队列(dequeue)取一个URL……如此往复,持续不断地访问全部互联网页,这就是互联网的广度优先遍历。

事实上,由于待下载URL集合存储在文件中,URL下载服务器只需要向待下载URL集合文件尾部追加URL记录,而URL调度器只需要从文件头顺序读取URL,这样就天然实现了先进先出的广度优先算法,如下图。

但是,广度优先搜索算法可能会导致爬虫一段时间内总是访问同一个网站,因为一个HTML页面内的链接常常是指向同一个网站的,这样就会使爬虫“不礼貌”。

通常我们针对一个网站,一次只下载一个页面,所以URL调度器需要将待下载URL根据域名进行分类。此外,不同网站的信息质量也有高低之分,爬虫应该优先爬取那些高质量的网站。优先级和域名都可以使用不同队列来区分,如下图。

首先优先级分类器会根据网页内容质量将域名分类(后面专栏会讲PageRank质量排名算法),并为不同质量等级的域名设置不同的优先级,然后将不同优先级记录在“域名优先级表”中。

接下来,按照广度优先算法,URL列表会从待下载URL集合文件中装载进来。根据“域名优先级表”中的优先级顺序,优先级分类器会将URL写入不同的队列中。

下一步,优先级队列选择器会根据优先级使用不同的权重,从这些优先级队列中随机获取URL,这样使得高优先级的URL有更多机会被选中。而被选中的URL都会交由域名分类器进行分类处理。域名分类器的分类依据就是“域名队列映射表”,这个表中记录了不同域名对应的队列。所以域名分类器可以顺利地将不同域名的URL写入不同的域名队列中。

最后,域名队列选择器将轮询所有的域名队列,从其中获得URL并分配给不同的URL下载服务器,进而完成下载处理。

去重算法

爬虫的去重包括两个方面,一个是URL,相同URL不再重复下载;一个是内容,相同页面内容不再重复存储。去重一方面是提高爬虫效率,避免无效爬取;另一方面提高搜索质量,避免相同内容在搜索结果中重复出现。URL去重可以使用布隆过滤器以提高效率。

内容去重首先要判断内容是否重复,由于爬虫存储着海量的网页,如果按照字符内容对每一个下载的页面都去和现有的页面比较是否重复,显然是不可能的。

Bajie计算页面内容的MD5值,通过判断下载页面的内容MD5值是否已经存在,判断内容是否重复。

如果把整个HTML内容都计算MD5,那么HTML中的微小改变就会导致MD5不同,事实上,不同网站即使相同内容的页面,也总会改成自己的HTML模板,导致HTML内容不同。

所以,比较内容重复的时候,需要将HTML里面的有效内容提取出来,也就是提取出去除HTML标签的文本信息,针对有效内容计算MD5。更加激进的做法是从有效内容中抽取一段话(比如最长的一句话),计算这段话的MD5,进而判断重复。

而一个内容MD5是否存在,需要在千亿级的数据上查找,如果用Hash表处理,计算和内存存储压力非常大,我们将用布隆过滤器代替Hash表,以优化性能。

高可用设计

Bajie的可用性主要关注两个方面,一是URL调度器或URL下载处理服务器宕机,二是下载超时或内容解析错误。

由于Bajie是一个离线系统,暂时停止爬取数据的话,不会产生严重的后果,所以Bajie并不需要像一般互联网系统那样进行高可用设计。但是当服务器宕机后重启时,系统需要能够正确恢复,保证既不会丢失数据,也不会重复下载。

所以,URL调度器和URL下载处理服务器都需要记录运行时状态,即存储本服务器已经加载的URL和已经处理完成的URL,这样宕机恢复的时候,就可以立刻读取到这些状态数据,进而使服务器恢复到宕机前的状态。对于URL下载处理服务器,Bajie采用Redis记录运行时状态数据。

此外,为了防止下载超时或内容解析错误,URL下载处理服务器会采用多线程(池)设计。每个线程独立完成一个URL的下载和处理,线程也需要捕获各种异常,不会使自己因为网络超时或者解析异常而退出。

小结

架构设计是一个权衡的艺术,不存在最好的架构,只存在最合适的架构。架构设计的目的是解决各种业务和技术问题,而解决问题的方法有很多种,每一种方法都需要付出各自的代价,同时又会带来各种新的问题。架构师就需要在这些方法中权衡选择,寻找成本最低的、代价最小的、自己和团队最能驾驭得住的解决方案。

因此,架构师也许不是团队中技术最好的那个人,但一定是对问题和解决方案优缺点理解最透彻的那个人。很多架构师把高可用挂在嘴上。可是,你了解你的系统的高可用的目的是什么吗?你的用户能接受的不可用下限在哪里?你为高可用付出的代价是什么?这些代价换来的回报是否值得?

我们在Bajie的设计中,核心就是URL调度器。通常在这样的大规模分布式系统中,核心组件是不允许单点的,也就是不允许单机部署,因为单机宕机就意味着核心功能的故障,也就意味着整个系统无法正常运行。

但是如果URL调度器采用分布式集群架构提高可用性,多服务器共同进行URL调度,就需要解决数据一致性和数据同步问题,反而会导致系统整体处理能力下降。而Bajie采用单机部署的的方式,虽然宕机时系统无法正常运行,但是只要在运维上保证能快速重新启动,长期看,系统整体处理能力反而更高。

此外,对于一个千亿级网页的爬虫系统而言,最主要的技术挑战应该是海量文件的存储与计算,这也确实是早期搜索引擎公司们的核心技术。但是,自从Google公开自己的大数据技术论文,而Hadoop开源实现了相关技术后,这些问题就变得容易很多了。Bajie的海量文件存储就使用了Hadoop分布式文件系统HDFS,我会在后面的《常见海量数据处理技术回顾》这一讲详细讨论它。

思考题

一个设计良好的爬虫需要面对的情况还有很多,你还能想到哪些文中没提及的情况?最好也能和我聊聊对应的设计方案。

欢迎在评论区分享你的思考,或者提出对这个设计文档的评审意见,我们共同进步。

数据从业者必读:抓取了一千亿个网页后我才明白,爬虫一点都不简单

编者按:互联网上有浩瀚的数据资源,要想抓取这些数据就离不开爬虫。鉴于网上免费开源的爬虫框架多如牛毛,很多人认为爬虫定是非常简单的事情。但是如果你要定期上规模地准确抓取各种大型网站的数据却是一项艰巨的挑战,其中包括网站的格式经常会变、架构必须能灵活伸缩应对规模变化同时要保持性能,与此同时还要挫败网站反机器人的手段以及维护数据质量。流行的Python爬虫框架Scrapy开发者Scrapinghub分享了他们抓取一千亿个网页后的经验之谈。

技术图片

  现在爬虫技术似乎是很容易的事情,但这种看法是很有迷惑性的。开源的库/框架、可视化的爬虫工具以及数据析取工具有很多,从网站抓取数据似乎易如反掌。然而,当你成规模地在网站上抓东西时,事情很快就会变得非常棘手。

  自2010年以来抓取超过1000亿个产品页面,我们将会通过系列文章来分享从中学到的经验教训,让你深入了解从电子商务商店中规模析取数据时所面临的挑战,并且跟你分享应对这些挑战的某些最佳实践。

  本文是该系列文章的第一篇,在这里我们将提供规模抓取产品数据所面临主要挑战的概览,以及Scrapinghub从抓取1000亿产品页面中学到的经验教训。

  成立于2010年的Scrapinghub是领先的数据析取公司之一,也是当今最健壮和流行的web爬虫框架Scrapy的作者。目前Scrapinghub每月抓取许多全球最大型电子商务公司的页面数超过80亿(其中30亿是产品页面)。

  对于那些对规模爬取网页技术感兴趣但对要不要建立专门的web爬取团队或者外包给专门的web爬取公司的人来说,最好看看这个免费指南,企业web爬虫:规模化web爬取技术指南

!!!规模爬取技术为什么重要?

跟标准的web爬取应用不一样的是,规模爬取电子商务产品数据有一项独特挑战使得web抓取要困难许多。

本质上这些挑战可归结为两件事情:速度和数据质量

由于时间通常是限制因素,规模抓取要求你的爬虫要以很高的速度抓取网页但又不能拖累数据质量。对速度的这张要求使得爬取大规模产品数据变得极具挑战性。

技术图片

挑战1——草率而且总是在变的网站格式

这一点很明显但也许不是最性感的挑战,但是草率而一直在变的网站格式是目前为止你在规模析取数据时将会面临的最大挑战。这未必是因为任务的复杂性,而是由于你要投入的时间和资源。

如果你花过时间开发过电子商务商店的爬虫的话,你就会知道电子商务网站代码之草率是一种流行病。这可不仅仅是HTML完构性或者偶尔的字符编码问题。这些年来我们遇到过形形色色的问题——HTTP响应代码的误用,损坏的JavaScript代码,或者Ajax的误用:

  • 停掉产品时移除页面的商店在网站升级后突然间会在404错误处理程序返回200响应码。
  • 不恰当的JSON转义破坏了部分页面的JavaScript代码(比如‘b0rk’d’),导致你需要用正则表达式来抓取那部分数据。
  • 滥用Ajax调用的商店以至于你只能靠渲染该页面(这会导致爬取慢很多)或者模仿API调用(导致要付出更多的开发努力)来获得数据。

像这样草率的代码会导致编写爬虫非常痛苦,但也会使得可视化爬取工具或者自动析取不再可行。

在规模爬取的时候,你不仅要浏览成百上千个有着草率代码的网站,还将被迫应对不断演变的网站。一条好的经验法则是要预计你的目标网站每隔2到3个月就会发生让你的爬虫工作不了的变化。

  这也许看起来不像是多大的事,但是当你规模抓取时,那些事件就会累积。比方说,Scrapinghub有一个规模比较大的电子商务项目大概有4000个爬虫抽取约1000个电子商务网站,意味着每天可能会经历20到30次爬虫失败。

  而且网站在不同地区、语言的变化,A/B测试以及包装/定价的派生也会制造出各种问题导致爬虫失败。

没有容易的解决方案

不幸的是,不存在银弹可以彻底解决这些问题。很多时候这只是随着规模而扩大投入更多资源到你的项目上才能解决的事情。再拿上一个例子来说吧,那个项目有18名全职的爬虫工程师以及3名专职的QA工程师来确保客户总能得到可靠的数据流。

不过,你的团队有经验以后就会学会如何开发出更加健壮的爬虫,从而检测并处置目标网站格式中的异常。

如何处理目标网站有各种布局可能的情况呢?用多个爬虫也许不是最好的做法,我们的最佳实践是只用一个产品爬虫来处理不同页面布局个各种可能规则和模式。你的爬虫可配置性越强越好。

尽管这些实践会让你的爬虫更加复杂(我们有些爬虫有好几千行),但它会确保你的爬虫更容易维护。

由于大多数公司日常都需要析取产品数据,等待几天让你的工程团队修复任何坏掉的爬虫不是可选项。当出现这些情况时,Scrapinghub会利用自己开发的基于机器学习的数据析取工具来作为后备,直到爬虫修复好。这个基于ML的析取工具会自动识别目标网站的目标字段(产品名称、价格、货币单位、图像、SKU等)并且返回想要的结果。

我们会在未来几周之内发布这项工具以及相关的指导文章,告诉大家如何将机器学习用到你的数据析取过程当中。

挑战 2:可伸缩的架构

你将面临的第二个挑战是建设一个可随每日请求数增长而扩充且性能不会下降的爬虫基础设施。

在规模析取产品数据时,一个串行爬取的简单web爬虫是不堪此任的。通常一个串行的web爬虫会循环发出请求,每一项请求都要2到3秒钟完成。

如果你的爬虫每天发出的请求数不到40000的话这种做法是没有问题的。然而,超过这个点你就得过渡到一种让你每天可以完成数百万请求而不会性能下降的爬虫架构。

这个话题得用一篇文章才能说得清楚,未来几周我们将发布一篇专门的文章来讨论如何设计和开发高吞吐量的爬取架构。然而,本节的剩余部分我们将讨论一些高级原则和最佳实践。

正如我们讨论过那样,在规模爬取产品数据时速度是关键。你需要确保在时间阈值范围内(通常是1天)可以找到并且爬取所有要求的产品页面。为此你需要做以下一些事情:

将产品发现与产品析取分开

为了规模爬取产品数据你需要将你的产品发现爬虫与产品析取爬虫分开。

产品发现爬虫的目标应该是让它浏览目前产品目录(或者“货架”)然后存储该目录下的产品URL供产品析取爬虫使用。

这个可以靠Scrapinghub 开发的开源工具Frontera之类的爬虫前端辅助完成。尽管Frontera原先的目的是配合Scrapy使用的,但它其实完全是不可知论者,可用于任何爬虫框架或者独立项目。在这篇文章中,我们分享了如何利用Frontera来规模抓取HackerNews的东西。

分配更多资源给产品析取

由于每一个产品目录“货架”可包含10到100种产品,而且析取产品数据需要的资源要比析取产品URL更多,发现爬虫通常运行要比产品析取爬虫更快。这种情况下,你需要有多个析取爬虫来对应每一个发现爬虫。一条好的经验法则是每10万个页面分配一个析取爬虫。

挑战 3:维护吞吐量性能

一级方程式的目标是将车上一切不必要的载荷都剔除掉,并且以速度之名将引擎最后一丝马力都榨干,从这个意义上来说规模抓取可以跟一级方程式相比较。规模web抓取也是一样的道理。

在析取大量数据时,在现有硬件资源条件下,你总是会想方设法要寻找请求周期最小化爬虫性能最大化的手段。这一切都是希望你能给每个请求节省下来那么几微秒的时间。

为此你的团队需要对web爬取框架、代理管理以及所使用的硬件具备深刻理解,这样才能对它们进行调整以优化性能。你还需要关注:

爬取效能

规模爬取时你应该始终把焦点放在以尽量少的请求析取所需数据上。任何额外请求或者数据析取都会放缓你爬取网站的节奏。在设计你的爬虫时请记住这些提示:

  • 作为最后一招,仅使用无界面浏览器,比如Splash或者Puppeteer来渲染JavaScript。用无界面浏览器渲染JavaScript同时爬取是非常耗资源的,会严重影响爬取的速度。
  • 如果你可以从货架页面(比如产品名称、价格、评分等)获得所需的数据而不需要向独立的产品页面提出请求的话,那就不要向产品页面发出请求。
  • 不要请求或者析取图像,除非迫不得已。

挑战 4:反机器人的对策

如果你批量抓取电子商务网站的话一定会遇到采用反机器人对策的网站。

规模小一点的网站其反机器人对策就是些基本手段(屏蔽发送请求过量的IP)。然而,较大的电子商务网站,比如Amazon等,会采用复杂的反机器人对策,比如Distil Networks、Incapsula或者Akamai等来使得析取数据困难许多。

代理

了解到这一点之后,任何项目想要规模抓取才数据,首要的基本需求就是得用代理。规模抓取数据时你需要可观的代理清单,而且需要实现必要的IP轮转、请求限制、会话管理以及黑名单逻辑来预防代理被屏蔽。

或者除非你有或者愿意用一支规模可观的团队管理你的代理,否则的话你应该把抓取流程中的这一部分外包出去。提供各种水平服务的代理服务有很多。

然而,我们的建议是找一家能够提供单个代理配置端点并且将所有的代理管理复杂性隐藏起来的代理提供商。在没有重新发明轮子、开发和维护自己的内部代理管理基础设施的情况下规模抓取就已经很耗资源了。

大多数大型电子商务公司都采用这种做法。一些全球最大型的电子商务网站采用Scrapinghub 开发的智能下载器Crawlera,这个东西的代理管理完全是外包的。当你的爬虫每天要发出2000万条请求时,把注意力放在分析数据而不是管理代理上会有意义得多。

代理以外

不幸的是,光靠使用代理服务并不足以确保你能规避大型电子商务网站的反机器人对策。越来越多的网站正在利用复杂的反机器人对策来监控你的爬虫行为,检测其是否真人访客。

这些范机器人对策不仅使得爬取电子商务网站越来越困难,而且克服这些手段如果做得不对的话也会严重拖累爬虫性能。

这些机器人对策有很大一部分使用到了JavaScript来确定请求是否来自于爬虫还是人(Javascript引擎检查、字体枚举、WebGL与Canvas等)。

不过正如前面所述,规模爬取时你希望限制可编写脚本的无界面浏览器(Splash 或者Puppeteer等)的使用,因为渲染页面的任何JavaScript都非常耗资源并且放慢爬取网站的速度。

这意味着为了确保你能取得必要的吞吐量让爬虫提交每天的产品数据,你往往需要痛苦地对目标网站采用的反机器人对策进行逆向工程,并且在不使用无界面浏览器的情况下设计你的爬虫抵消那些对策。

挑战 5:数据质量

从数据科学家的角度来说,任何网站爬取项目最重要的考虑是析取数据的质量。规模爬取只会令这一关注变得更加重要。

当每天都要析取数百万数据点时,想靠人工来验证数据是否干净和完整是不可能的。变脏或者不完整的数据很容易就会流入到你的数据流里面,进而破坏了数据分析的效果。

尤其是在抓取同一个的不同版本(不同的语言、地区等)或者不同商店上的产品时更是如此。

在爬虫开发的设计阶段,需要进行仔细的QA流程,爬虫代码要经过同行评审和测试以确保用最可靠的方式析取到想要的数据。确保最高数据质量的最好的办法是部署一套自动化QA监控系统。

作为任何数据析取项目的一部分,你需要计划和开发一套监控系统,这套系统将提醒你任何不一致的数据以及发生的爬虫错误。Scrapinghub开发了一个机器学习算法来检测:

  • 数据验证错误——每一个数据项都有定义好的遵循一致模式的数据类型和值。我们的数据验证算法会提醒项目的QA团队任何与预期数据类型不一致的数据项,然后再进行人工检查、提醒已验证或者标记为错误。
  • 产品差异化错误——从同一网站的多个版本(不同语言、地区)爬取相同产品数据时,有可能变量或者像产品重量或者尺寸这样本该是固定值的数据项也会不一样。这可能是网站反机器人对策向你的一到多个爬虫提供篡改信息的结果。再次地,你需要算法来识别和标记类似这样的情况。
  • 基于数量的不一致性——另一个关键的监控脚本是检测返回记录的任何异常变化。这可能预示网站已经做出改变或者你的爬虫被提供了篡改的信息。
  • 网站变化——目标网站发生的结构性改变是爬虫失效的主要原因。我们的专用监控系统会监控到这一点。该工具会对目标网站进行频繁的检查,确保自从上次抓取之后没有发生任何变化。如果改变被发现,它也会发出通知。

总结

正如你所看到那样,规模抓取产品数据会面临一系列的独特挑战。希望这篇文章能够让你更加意识到相关挑战,并且就如何解决这些问题获得启发。

原文链接:https://baijiahao.baidu.com/s?id=1606482126832777393&wfr=spider&for=pc

原文链接:https://blog.scrapinghub.com/web-scraping-at-scale-lessons-learned-scraping-100-billion-products-pages

好文章拿来读一读。编辑:不良将。

以上是关于5 04 | 网页爬虫设计:如何下载千亿级网页?的主要内容,如果未能解决你的问题,请参考以下文章

爬虫很简单么?直到我抓取了一千亿个网页后我懂!爬虫真不简单!

数据从业者必读:抓取了一千亿个网页后我才明白,爬虫一点都不简单

网页搜集系统

网页搜集系统

网页搜集系统

如何驾驭MySQL 架构设计,实现千亿级数据分库分表?