目录
分布式爬虫要点
现在有爬虫A、B、C分别位于三台服务器,三个爬虫都爬取同一个网站,那么,对于爬虫B来说,那个URL是爬虫A或者C已经爬取过的,爬虫B需要避免重复爬取;还有就是三个爬虫各自都需要对URL进行去重,如果各自去重,其他爬虫怎么知道那个URL去没去重,因此,我们需要一个第三方的状态管理器,它是一个单独的服务,统一管理这三个爬虫的状态,并调度各个爬虫进行协同操作,所以,第三方的状态管理器是必须要实现的。
分布式爬虫的优点
充分利用多机器的宽带加速爬取;
充分利用多机器的IP加速爬取。
分布式需要解决的问题
request队列集中管理
scrapy数据流图里,request在schedule调度器里是存放在queen队列里的,队列存放于本机内存里的,其他机器的爬虫是获取(共享)到本机内存里的内容,所以,scrapy是不支持分布式的,request队列需要做成集中管理。
去重集中管理
scrapy里有个去重的扩展,它的原理是通过内存的set()
集合来做去重的管理,这里也牵扯到本机内存的问题,所以,去重也需要做集中管理。
关于集中管理,不能放到scrapy中,因为scrapy没有办法提供方法,让外部访问scrapy内部,所以,集中管理必须放到第三方的组件来做,这个第三方的组件就是Scrapy-Redis。
Redis的使用
Scrapy-Redis 需要先安装Redis,也需要知道Redis的命令,具体安装与命令,自己搜索。也可以参考:
- Redis教程:http://www.runoob.com/redis/redis-tutorial.html
- Redis命令大全:http://redisdoc.com/
Scrapy-Redis
1、安装Redis
进入到虚拟环境,使用命令:pip install redis
安装Redis到虚拟环境里
2、setting.py设置
1 2 3 4 5 6 7 8 9 10 |
# 启用redis中的调度存储请求队列。 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 确保所有的spider通过redis共享相同的副本。 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 在redis中存储item数据。 ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 300 } |
scrapy-redis创建步骤
1、新建scrapy项目
创建虚拟环境,我命名这个虚拟环境为:article_spider
进入虚拟环境article_spider,使用命令:scrapy startproject ScrapyRedisTest
创建名为ScrapyRedisTest的scrapy项目。
注意,如果不想再创建一个新的虚拟环境(需要重新安装各种库),而是使用旧的虚拟环境,在pycharm下:File》settings,在搜索框里输入“inter”找到Project Interpreter,按图设置:
最后,一路点确认(OK)下来就可以了。
2、下载Scrapy-Redis源码
进入项目ScrapyRedisTest的根目录,到GitHub下载Scrapy-Redis:https://github.com/rmax/scrapy-redis,通过Git或者下载Zip压缩包,下载Scrapy-Redis到本地。
把scrapy-redis\src下的scrapy_redis文件夹,复制到项目ScrapyRedisTest的根目录下
3、编写Scrapy-Redis代码
在spider里,新建爬虫代码:jobbole.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
引入RedisSpider from scrapy_redis.spiders import RedisSpider # 爬虫继承自RedisSpider class JobboleSpider(RedisSpider): name = 'jobbole' allowed_domains = ['blog.jobbole.com'] # start_urls改存放在Redis里 # redis_key 存放在Redis中的键,jobbole是键, # start_urls 需要在Redis界面中输入 redis_key = 'jobbole:start_urls' def parse(self, response): # 处理逻辑 pass |
4、在setting里设置值:
1 2 3 4 5 6 7 8 9 10 11 12 |
# 启用redis中的调度存储请求队列. # scrapy的Scheduler调度器,由Scrapy-Redis接管 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 确保所有的蜘蛛通过redis共享相同的去重器. # scrapy的去重机制,由Scrapy-Redis接管 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # item数据存入Redis中. ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 300 } |
5、把main.py在根目录创建起来:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/usr/bin/env python # -*- coding: utf-8 -*- #scrapy提供的命令行执行库 from scrapy.cmdline import execute import os import sys #把项目根目录路径加入到python文件路径查找列表中 sys.path.append(os.path.abspath(os.path.dirname(__file__))) #拼写命令,交给scrapy.cmdline的execute去转化为cmd命令执行 execute(['scrapy','crawl','jobbole']) |
6、在Redis里lpush进去start_urls
运行main.py,可以在控制台中看到,Scrapy-Redis正在监听Redis,等待接收start_urls:
然后去Redis界面,输入keys *
,可以看到,jobbole:scheduler(调度器)、jobbole:requests(请求的URL)、jobbole:dupefilter(去重器)这三个的数据都放在了Redis中,实现数据共享。
7、其他的操作和scrapy没什么区别。