10. 设计爬虫

需求和目标

爬尽可能多的网页内容。大概有10000亿个网页。需要爬他们至少每周一次。
1T /1m (一周假设有1M 秒)
那么大概有1M 的网页每秒要爬。
假设一个网页平均10K,就是10P的数据。

非功能性需求:

  1. 可扩展性: 如果要爬的网页量增多,可以水平扩展,增加并行度
  2. 健壮性: 网络里充满了陷阱,比如糟糕的HTML,不响应的服务器,节点崩溃,恶意链接
  3. 礼貌: 爬虫不应该在短时间内对网站提出太多的请求
  4. 可演化性: 为了支持性的特性,系统是灵活的,只需要最小的变化

服务

1653527134(1).png

首先我们需要有很多爬虫模块。

  1. 一组种子 URL( 作为爬虫开始的起点,这里的选取策略是开放式的)
  2. URL队列(这里面存的是待爬去的URL,会交给分布式WORKER去实际下载URL里的内容)
  3. WORKER 里面 会包含几个模块(一个是HTML下载,一个是DNS解析,content parser, content dedup,url extractor)
  4. 上述步骤都做完了,会把解析后的内容存到CONTENT STORAGE 里。
  5. 然后再把这个HTTP PAGE里的链接到URL取出来,加到任务数据库(task service)中。(这里面可以也包括几个子模块,如url filter, 去handle error links, blacklisted url; url去重)
1653527049(1).png

爬虫模块负责从TASK SERVICE里取任务。然后加到MQ (URL FRONTIER)
同时爬到之后又把URL 给TASK SERVICE 存新任务。
那么TASK SERVICE 就是用来做任务管理的。
最后还需要一个存储服务,用来存爬到的信息。
我们使用RDBMS 来存TASKS,BIG TABLE来存网页内容(因为数据量过大,肯定需要HDFS)

首先说下单机爬虫,爬虫从一些根WEB SEEDS抓到网页内容,然后交给2个模块,存储内容模块,负责提取有用信息,放进BIGTABLE储存。EXTRACTOR模块,负责获取网站里的URL,然后做一个判定是否已经抓过,然后放进TASK SERVICE的URL QUEUE里。

随后我们引入多线程来提取抓取速度,因为访问网页的时候是NETWORK IO BLOCK。

为了防止多个线程的线程安全问题。我们可以使用线程安全的阻塞队列。如果没有阻塞队列,我们需要用锁来防止多线程竞争。

但是越多的线程不意味越好的性能。
因为1.线程多,那么切换开销也大。
2.超过CPU CORE的数量,多的线程也是在一个CPU的时间片里反复切换。
3.线程需要耗费资源,有限制
4.网络带宽也有限制。

DFS VS BFS

DFS 因会深度过深,所以在这个场景里BFS更好。
但BFS也会带来2个新问题,一个是LINK有环,另一个是大多数BFS出来的LINK都是属于同一个HOSTNAME,那么就会不太礼貌(短时间朝一个HOST发送大量请求),同时BFS 用的FIFO的队列,没办法考虑URL的优先级的设置问题。

要解决上面的问题,我们就要仔细设计一下存储TASK 的MQ(URL FRONTIER)了。


1653527769(1).png

我们可以对多个HOSTNAME,建立单独的QUEUE,然后然一个WORKER负责一个QUEUE,并且在里面处理的时候,控制速率,可以解决这个问题,如上图。

不过更好的做法是,怕取一个任务后,可以更新这个HOST,下次可以爬取的时间,然后如果WORKER拿到之后,发现时间还没到,可以重新放回队列里。这样可以让一个QUEUE,拥有更多的HOSTNAME。

在处理优先级的时候,我们也可以根据不同的优先级开多个队列。然后QUEUE SELECTOR的时候根据优先级不同配置不同的概率,去选择哪个队列里取数据


1653532221(1).png

然后我们可以对DNS的获取 做一层CACHE,来起到性能优化的效果。(因为从URL到IP,去DNS拿 需要10ms ~200ms的开销)(DNS CACHE 会自己有吗?)

局部性优化,知道网站HOST在哪,然后用更近的WORKER 去DOWNLOAD,可以加快下载速度

设置TIMEOUT,来防止某些URL 长时间没有响应

存储

WEB 内容就是直接存下来到HDFS上即可,放在BIG TABLE上 是方便QUERY。
下面主要设计TASK TABLE
一个TASK,需要目标URL,TASK 状态,优先级,有效时间。
TASK 状态,分为在爬,爬好了,还没开始爬。
有效时间,代表到这个时间前,爬好了都无需再爬。


image.png

优化

首先为了提高性能,我们需要构建分布式的爬虫。那么一个TASK DB,需要变成分布式。
我们可以用HOST NAME 来做SHARDING KEY。这样一个网站下的不同网页就会分配到同一个服务器了。

如何HANDLE 一个网页连接失败了?

很有可能是这个网站不存在了。为了不反复让费资源。我们可以用指数级拓展法。
比如现在是一周爬一次,挂了之后,改为2周爬一次。还挂改为4周爬一次。以此类推。
一旦有一次好了,就再除以2.

如何避免死循环?

已经爬过的我们设定了下次再爬的时间。这样可以避免死循环。
如果是不同的URL,而是过多的资源被一个HOST占用。我们可以限定配额,当这个HOST下的网页超过配额了。就先去爬别的,等别的爬的多了,那么再爬一点这个网页。让他始终低于一个比例。

如何避免多个不同的网页内容一样?

我们可以对网页内容计算一个CHECKSUM,如果这个CHECKSUM之前出现过。就不再存储。
CHECKSUM 64位就够了。
那么1TRILLION个网页,大概需要8 T 的空间。

如何提高访问页面的性能?

建立一个DNS CACHE 服务器,这样可以不用每次都到DNS 服务器上去把HOSTNAME 转换为IP。

可不可以使用布隆过滤器来去重URL

布隆过滤器的特点是有可能有,没有一定没有。这个特性会造成一些本来应该爬的URL,会被当成已经存在的,而不去爬。所以不太合适。

如何容错

一旦一个CRAWLER挂了就再起一个
一旦一个TASK SERVICE 挂了,我们需要定期把QUEUE的状态写进磁盘,当做一个存档点。这样下次可以恢复。
一旦一个STORAGE SERVICE挂了。我们直接用BIG TABLE 的容错机制来保护。外面应该有负载均衡器,会保障CRAWLER可以到健康的SERVICE上继续存储。

如何设置每个URL的优先级

我们可以手动设置优先级,把重要的一些URL的特征提取出来,或者建立几个优先级的名单。
当然也可以用算法来设置优先级。
1.首先我们需要一组根页面,使得每个页面分配一定的信用。
2.随后我们爬去这些页面,找到他有的LINK。同时把这个页面的信用清0
3.信用要交10%的税给LAMBDA页面。随后平均的分给下面的LINK。
4.信用高的页面会优先处理。
5.按照上述步骤不断去做。

因为都要交税给LAMBDA页面,所以LAMBDA页面信用涨的很快,很快就会要被处理。这个时候我们把这些信用平均分给所有DB未爬的页面上。
这样的好处就使得,因为有税的存在,那些只有内部链接的页面,就会不断信用流失。而正常的页面因为有外部链接,则不会发生这个问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,382评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 《这就是搜索引擎》这本书的第二章是关于爬虫的,干货很多(文章几乎没有废话,所以复制居多),可以参考搜索引擎是如何构...
    SeanCheney阅读 2,089评论 0 20
  • 女神你一直住在我的心里面 一直都在我的身边陪伴着我 在浩瀚的心之微空间我看着你 见到你在那个寂静中自由翱翔 啊啊我...
    亲爱的田田阅读 141评论 0 1
  • 因为有期待,难免会感到凄凉。 其实一开始就看出来凶手是谁,不过还是耐心看下去了。 前岛的妻子的杀人动机还比较好理解...
    淑淑女子阅读 442评论 0 1