爬虫总结(四)-- 分布式爬虫

分布式爬虫的演习。

分布式爬虫问题其实也就是多台机器多个 spider 对 多个 url 的同时处理问题,怎样 schedule 这些 url,怎样汇总 spider 抓取的数据。最简单粗暴的方法就是将 url 进行分片,交给不同机器,最后对不同机器抓取的数据进行汇总。然而这样每个 spider 只能对自己处理的 url 去重,没办法全局的去重,另外性能也很难控制,可能有某台机器很早就跑完了,而别的机器还要跑很久。另一种思路就是把 url 存在某个地方,共享给所有的机器,总的调度器来分配请求,判断 spider 有没有闲置,闲置了就继续给它任务,直到所有的 url 都爬完,这种方法解决了去重问题(下面会具体讲到),也能提高性能,scrapy-redis 就实现了这样一个完整框架,总的来说,这更适合广度优先的爬取。

Scrapyd

Scrapy 并没有提供内置的分布式抓取功能,不过有很多方法可以帮你实现。

如果你有很多个spider,最简单的方式就是启动多个 Scrapyd 实例,然后将spider分布到各个机器上面。

如果你想多个机器运行同一个spider,可以将url分片后交给每个机器上面的spider。比如你把URL分成3份

http://somedomain.com/urls-to-crawl/spider1/part1.list
http://somedomain.com/urls-to-crawl/spider1/part2.list
http://somedomain.com/urls-to-crawl/spider1/part3.list

然后运行3个 Scrapyd 实例,分别启动它们,并传递part参数

curl http://scrapy1.mycompany.com:6800/schedule.json -d project=myproject -d spider=spider1 -d part=1
curl http://scrapy2.mycompany.com:6800/schedule.json -d project=myproject -d spider=spider1 -d part=2
curl http://scrapy3.mycompany.com:6800/schedule.json -d project=myproject -d spider=spider1 

Crawlera

这个,花钱就可以轻易解决~ 直达

Scrapy-redis

Redis 是高性能的 key-value 数据库。我们知道 MongoDB 将数据保存在了硬盘里,而 Redis 的神奇之处在于它将数据保存在了内存中,因此带来了更高的性能。

分布式原理

scrapy-redis实现分布式,其实从原理上来说很简单,这里为描述方便,我们把自己的核心服务器称为 master,而把用于跑爬虫程序的机器称为 slave。

回顾 scrapy 框架,我们首先给定一些start_urls,spider 最先访问 start_urls 里面的 url,再根据我们的 parse 函数,对里面的元素、或者是其他的二级、三级页面进行抓取。而要实现分布式,只需要在这个starts_urls里面做文章就行了。进一步描述如下:

  1. master 产生 starts_urls,url 会被封装成 request 放到 redis 中的 spider:requests,总的 scheduler 会从这里分配 request,当这里的 request 分配完后,会继续分配 start_urls 里的 url。

  2. slave 从 master 的 redis 中取出待抓取的 request,下载完网页之后就把网页的内容发送回 master 的 redis,key 是 spider:items。scrapy 可以通过 settings 来让 spider 爬取结束之后不自动关闭,而是不断的去询问队列里有没有新的 url,如果有新的 url,那么继续获取 url 并进行爬取,所以这一过程将不断循环。

  3. master 里的 reids 还有一个 key 是 “spider:dupefilter” 用来存储抓取过的 url 的 fingerprint(使用哈希函数将url运算后的结果),防止重复抓取,只要 redis 不清空,就可以进行断点续爬。

对于已有的 scrapy 程序,对其扩展成分布式程序还是比较容易的。总的来说就是以下几步:

  1. 找一台高性能服务器,用于 redis 队列的维护以及数据的存储。
  2. 扩展 scrapy 程序,让其通过服务器的 redis 来获取 start_urls,并改写 pipeline 里数据存储部分,把存储地址改为服务器地址。
  3. 在服务器上写一些生成url的脚本,并定期执行。

关于 scheduler 到底是怎么进行调度的,需要看源码进行分析。

源码分析

可能上面的描述还是不够清楚,干脆看一下源码吧,scrapy-redis 主要要一下几个文件。

零件分析

  1. connection.py
    根据 settings 里的配置实例化 redis 连接,被 dupefilter 和 scheduler 调用。

  2. dupefilter.py
    对 request 进行去重,使用了 redis 的 set。

  3. queue.py
    三种 queue, SpiderQueue(FIFO), SpiderPriorityQueue,以及 SpiderStack(LIFI)。默认使用的是第二种。

  4. pipelines.py
    分布式处理,将 item 存储在 redis 中。

  5. scheduler.py
    取代 scrapy 自带的 scheduler,实现分布式调度,数据结构来自 queue。

  6. spider.py
    定义 RedisSpider.py, 继承了 RedisMixin 和 CrawlSpider。

由上可知,scrapy-redis 实现的 爬虫分布式 和 item处理分布式 就是由模块 scheduler 和模块 pipelines 实现。上述其它模块作为为二者辅助的功能模块。

调度过程

初始化

spider 被初始化时,同时会初始化一个对应的 scheduler 对象,这个调度器对象通过读取 settings,配置好自己的调度容器 queue 和判重工具dupefilter。

判重 & 进入调度池

每当一个 spider 产出一个 request 的时候,scrapy 内核会把这个 request 递交给这个 spider 对应的 scheduler 对象进行调度,scheduler 对象通过访问 redis 对 request 进行判重,如果不重复就把他添加进 redis 中的调度池。

调度

当调度条件满足时,scheduler 对象就从 redis 的调度池中取出一个 request 发送给spider,让 spider 爬取,若爬取过程中返回更多的url,那么继续进行直至所有的 request 完成。在这个过程中通过 connect signals.spider_idle 信号对 crawler 状态的监视,scheduler 对象发现 这个 spider 爬取了所有暂时可用 url,对应的 redis 的调度池空了,于是触发信号 spider_idle,spider收到这个信号之后,直接连接 redis 读取 strart_url池,拿去新的一批 url,返回新的 make_requests_from_url(url) 给引擎,进而交给调度器调度。

熟悉了原理其实可以自己来写 scheduler,自己定义调度优先级和顺序,

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值