scrapy 本身并不是一个分布式框架,而 Scrapy-redis 库使得分布式成为可能;
Scrapy-redis 并没有重构框架,而是基于redis数据库重写了框架的某些组件。
分布式框架要解决两个问题
分配爬取任务:为每个爬虫分配不重复的任务
scrapy-redis 使用 redis 数据库存储所有请求,利用 redis 数据库实现请求队列,所有爬虫从该队列中获取任务,并将新产生的请求添加到该队列中;
汇总爬取数据:将所有爬虫的数据汇总到一处
scrapy-redis 使用 RedisPipeline 将数据存储于同一个 redis 数据库中,并用 twisted 框架实现并发存储。
具体实现参考
Scrapy-redis 源码 https://github.com/rmax/scrapy-redis/tree/master/src/scrapy_redis
环境搭建
1. 多台服务器
2. 分别配置 单机爬虫 所需环境
3. 选择一台服务器搭建 redis 数据库
4. 测试集群能否连接 redis
具体实施
1. 创建单机项目
2. 修改配置文件
# 必选项 # ================================================================= # 指定爬虫所使用的Redis数据库(在云服务器116.29.35.201 上) REDIS_URL = 'redis://116.29.35.201:6379' # 使用scrapy_redis的调度器替代Scrapy 原版调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 使用scrapy_redis的RFPDupeFilter作为去重过滤器 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 启用scrapy_redis的RedisPipeline将爬取到的数据汇总到Redis数据库 ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 300, } # 可选项 # ================================================================= #爬虫停止后,保留/清理Redis中的请求队列以及去重集合 # True:保留,False:清理,默认为False SCHEDULER_PERSIST = True
3. 修改爬虫
from scrapy_redis.spiders import RedisSpider # 1.更改基类 # class BooksSpider(spider.Spider): class BooksSpider(RedisSpider): # 2.注释 start_urls # start_urls = ['http://books.toscrape.com/']
【如何为多个爬虫设置起始爬取点】
单机爬虫 的起始爬取点由 start_urls 确定,但是分布式去掉了 start_urls,然后重写了 start_requests 方法,它尝试从 redis 数据库的某个特定列表中获取起始爬取点,构造request对象,并设置 dont_filter=False,
该列表可通过配置文件设定,REDIS_START_URLS_KEY,默认为 <spider_name>:start_urls;
在分布式爬取时,运行所有爬虫后,需要手动向该列表添加起始爬取点,之后只有其中一个爬虫获取到该起始点,避免重复。
4. 分发代码到其他机器
5. 每台机器上运行爬虫
6. 爬虫处于等待状态,在任一台机器上连接redis,设置爬取起始点
lpush books:start_urls 'http://books.toscrape.com'
其中一个爬虫获取该url,此后整个爬虫开始运转。
参考资料:
《精通scrapy网络爬虫》 pdf