1、分布式爬虫 scrapy - redis
scrapy 分布式爬虫
Scrapy 并没有提供内置的机制支持分布式(多服务器)爬取。不过还是有办法进行分布式爬取, 取决于您要怎么分布了。
如果您有很多spider,那分布负载最简单的办法就是启动多个Scrapyd,并分配到不同机器上。
如果想要在多个机器上运行一个单独的spider,那您可以将要爬取的 url 进行分块,并发送给spider。 例如:
首先,准备要爬取的 url 列表,并分配到不同的文件 url 里:
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个不同的 Scrapd 服务器中启动 spider。spider 会接收一个(spider)参数 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 -d part=3
scrapy-redis 分布式爬虫
scrapy-redis 巧妙的利用 redis 队列实现 request queue 和 items queue,利用 redis 的 set 实现 request 的去重,将 scrapy 从单台机器扩展多台机器,实现较大规模的爬虫集群
Scrapy-Redis 架构分析
scrapy 任务调度是基于文件系统,这样只能在单机执行 crawl。
scrapy-redis 将待抓取 request 请求信息 和 数据 items 信息 的存取放到 redis queue 里,使多台服务器可以同时执行 crawl 和 items process,大大提升了数据爬取和处理的效率。
scrapy-redis 是基于 redis 的 scrapy 组件,主要功能如下:
- 分布式爬虫。多个爬虫实例分享一个 redis request 队列,非常适合大范围多域名的爬虫集群
- 分布式后处理。爬虫抓取到的 items push 到一个 redis items 队列,这就意味着可以开启多个 items processes 来处理抓取到的数据,比如存储到 Mongodb、Mysql
- 基于 scrapy 即插即用组件。Scheduler + Duplication Filter、Item Pipeline、 Base Spiders
scrapy 原生架构
分析 scrapy-redis 的架构之前先回顾一下 scrapy 的架构
- 调度器(Scheduler):调度器维护 request 队列,每次执行取出一个 request。
- Spiders:Spider 是 Scrapy 用户编写用于分析 response,提取 item 以及跟进额外的 URL 的类。每个 spider 负责处理一个特定 (或一些) 网站。
- Item Pipeline:Item Pipeline 负责处理被 spider 提取出来的 item。典型的处理有清理、验证数据及持久化(例如存取到数据库中)。
如上图所示,scrapy-redis 在 scrapy 的架构上增加了 redis,基于 redis 的特性拓展了如下组件:
- 调度器(Scheduler)
scrapy-redis 调度器通过 redis 的 set 不重复的特性, 巧妙的实现了Duplication Filter去重(DupeFilter set存放爬取过的request)。 Spider 新生成的 request,将 request 的指纹到 redis 的 DupeFilter set 检查是否重复, 并将不重复的request push写入redis的request队列。 调度器每次从 redis 的 request 队列里根据优先级 pop 出一个 request, 将此 request 发给 spider 处理。
- Item Pipeline
将 Spider 爬取到的 Item 给 scrapy-redis 的 Item Pipeline, 将爬取到的 Item 存入 redis 的 items 队列。可以很方便的从 items 队列中提取 item, 从而实现 items processes 集群
总结
scrapy-redis 巧妙的利用 redis 实现 request queue 和 items queue,利用 redis 的 set 实现 request 的去重,将 scrapy 从单台机器扩展多台机器,实现较大规模的爬虫集群
scrapy-redis 安装
文档: https://scrapy-redis.readthedocs.org.
- 安装 scrapy-redis:pip install scrapy-redis
scrapy-redis 源码截图:
可以看到 scrapy-redis 的 spiders.py 模块,导入了 scrapy.spiders 的 Spider、CrawlSpider,然后重新写了两个类 RedisSpiders、RedisCrawlSpider,分别继承 Spider、CrawlSpider,所以如果要想从 redis 读取任务,需要把自己写的 spider 继承 RedisSpiders、RedisCrawlSpider,而不是 scrapy 的 Spider、CrawlSpider。。。
scrapy-redis 使用 项目案例( 抓取校花网图片 )
:http://www.521609.com/daxuexiaohua/
:https://www.51tietu.net/xiaohua/
(
scrapy_redis.spiders
下有两个类 RedisSpider 和 RedisCrawlSpider,能够使 spider 从 Redis 读取 start_urls,然后执行爬取,若爬取过程中返回更多的 request url,那么它会继续进行直至所有的 request 完成之后,再从 redis start_urls 中读取下一个 url,循环这个过程 )
创建 scrapy-redis 的工程目录
方法 1:命令行执行:scrapy startproject MyScrapyRedis,然后自己写的 spider 继承 RedisSpider 或者 RedisCrawlSpider ,设置对应的 redis_key ,即队列的在 redis 中的 key。注意:这个需要手动 在 setting.py 里面配置设置。( 参考配置:https://github.com/rmax/scrapy-redis )
方法 2:使用 scrapy-redis 的 example 来修改。先从 github ( https://github.com/rmax/scrapy-redis ) 上拿到 scrapy-redis 的 example,然后将里面的 example-project 目录移到指定的地址。
tree 查看项目目录
修改 settings.py ( 参考配置:https://github.com/rmax/scrapy-redis )