前言:

爬虫是偏IO型的任务,分布式爬虫的实现难度比分布式计算和分布式存储简单得多。 
个人以为分布式爬虫需要考虑的点主要有以下几个:

  • 爬虫任务的统一调度
  • 爬虫任务的统一去重
  • 存储问题
  • 速度问题
  • 足够“健壮”的情况下实现起来越简单/方便越好
  • 最好支持“断点续爬”功能

Python分布式爬虫比较常用的应该是scrapy框架加上Redis内存数据库,中间的调度任务等用scrapy-redis模块实现。 
此处简单介绍一下基于Redis的三种分布式策略,其实它们之间还是很相似的,只是为适应不同的网络或爬虫环境作了一些调整而已(如有错误欢迎留言拍砖)。

【策略一】


Slaver端从Master端拿任务(Request/url/ID)进行数据抓取,在抓取数据的同时也生成新任务,并将任务抛给Master。Master端只有一个Redis数据库,负责对Slaver提交的任务进行去重、加入待爬队列。

优点: scrapy-redis默认使用的就是这种策略,我们实现起来很简单,因为任务调度等工作scrapy-redis都已经帮我们做好了,我们只需要继承RedisSpider、指定redis_key就行了。 
缺点: scrapy-redis调度的任务是Request对象,里面信息量比较大(不仅包含url,还有callback函数、headers等信息),导致的结果就是会降低爬虫速度、而且会占用Redis大量的存储空间。当然我们可以重写方法实现调度url或者用户ID。

【策略二】


这是对策略的一种优化改进:在Master端跑一个程序去生成任务(Request/url/ID)。Master端负责的是生产任务,并把任务去重、加入到待爬队列。Slaver只管从Master端拿任务去爬。

优点: 将生成任务和抓取数据分开,分工明确,减少了Master和Slaver之间的数据交流;Master端生成任务还有一个好处就是:可以很方便地重写判重策略(当数据量大时优化判重的性能和速度还是很重要的)。 
缺点: 像QQ或者新浪微博这种网站,发送一个请求,返回的内容里面可能包含几十个待爬的用户ID,即几十个新爬虫任务。但有些网站一个请求只能得到一两个新任务,并且返回的内容里也包含爬虫要抓取的目标信息,如果将生成任务和抓取任务分开反而会降低爬虫抓取效率。毕竟带宽也是爬虫的一个瓶颈问题,我们要秉着发送尽量少的请求为原则,同时也是为了减轻网站服务器的压力,要做一只有道德的Crawler。所以,视情况而定。

【策略三】


Master中只有一个集合,它只有查询的作用。Slaver在遇到新任务时询问Master此任务是否已爬,如果未爬则加入Slaver自己的待爬队列中,Master把此任务记为已爬。它和策略一比较像,但明显比策略一简单。策略一的简单是因为有scrapy-redis实现了scheduler中间件,它并不适用于非scrapy框架的爬虫。

优点: 实现简单,非scrapy框架的爬虫也适用。Master端压力比较小,Master与Slaver的数据交流也不大。 
缺点: “健壮性”不够,需要另外定时保存待爬队列以实现“断点续爬”功能。各Slaver的待爬任务不通用。

结语:

如果把Slaver比作工人,把Master比作工头。策略一就是工人遇到新任务都上报给工头,需要干活的时候就去工头那里领任务;策略二就是工头去找新任务,工人只管从工头那里领任务干活;策略三就是工人遇到新任务时询问工头此任务是否有人做了,没有的话工人就将此任务加到自己的“行程表”。

最新文章

  1. AppBoxPro - 细粒度通用权限管理框架(可控制表格行内按钮)源码提供下载
  2. mongodb学习(一)
  3. 2016暑假多校联合---Windows 10
  4. 64位系统使用Access 数据库文件的彻底解决方法
  5. js计算在线时长
  6. Android 和iOS 中关于View 的一点知识
  7. HttpClient(4.3.5) - 简单示例
  8. C# 自定义控件制作和使用实例(winform)
  9. 寒哥教你学 iOS - 经验漫谈(转)
  10. Swagger 生成 ASP.NET Web API
  11. DateTime.ParseExact
  12. 浅谈数据结构之KMP(串中的模式匹配算法)
  13. Android使用 startActivityForResult 、 onActivityResult 时的注意事项
  14. python之路第二天 随便记记 今天主要很郁闷
  15. 201521123066 《java程序设计》第一周学习总结
  16. cocos2d-x 托付模式的巧妙运用——附源代码(一)
  17. 学习Javascript闭包(Closure)及几个经典面试题理解
  18. EasyMock 简单使用
  19. 中间件之Kafka
  20. loback学习

热门文章

  1. Scanner类nextLine()和next()的区别和使用方法
  2. Word Cloud (词云) - JavaScript
  3. 用.NetReactor保护您的源码[转][修改]
  4. 16-1 WEB存储基本操作
  5. 472 Concatenated Words 连接的单词
  6. .net 发送邮件验证码
  7. AJPFX:如何保证对象唯一性呢?
  8. VMware Workstation安装CentOS 7和开发环境
  9. Python学习 Day 4 函数 切片 迭代 列表生成式 生成器
  10. QPushButton注册事件过滤器后按钮消失