Contents
1. 简单原理
我们知道scrapy大致的原理是这样,首先会在start_requests 这个方法里发出一些请求url,然后在parse里进行解析,解析的item抛给pipeline进行处理. parse 如果又解析到url,抛出,先看下是否要过滤这个url,是否重复了,如果没有重复,发一个新请求这个url,再调用别的parse进行处理。直到待请求的url都为空,就停止爬虫。
import scrapy from tutorial.items import TutorialItem class QuotesSpider(scrapy.Spider): name = "quotes" def start_requests(self): url = 'http://quotes.toscrape.com/tag/humor/' yield scrapy.Request(url) def parse(self, response): item = TutorialItem() for quote in response.css('div.quote'): item['body'] = quote.css('span.text::text').extract_first() item['author'] = quote.css('small.author::text').extract_first() yield item next_page = response.css('li.next a::attr("href")').extract_first() if next_page is not None: yield response.follow(next_page, self.parse)
默认的scrapy也支持暂停爬虫,保存到本地,下一次再进行爬。但是这样就没法支持分布式啊。
scrapy-redis 就是为了支持分布式做的。它做了什么呢?把这些数据保存到redis中,让每个爬虫来对redis中的url进行解析。有个dupefilter来过滤重复的请求,item用来存储所有的item,request 是待爬队列。request如果爬了的,就会pop,删除,所以完整爬完request就没有数据了。就是用了redis数据库来实现了分布式。
2. 准备工作
我的是Mac环境。
2.1 要先安装scrapy-redis
sudo pip3 install scrapy-redis
2.2 安装redis
brew install redis
如果没有brew,要先安装brew
如果在终端中输入 redis-server,看下下面的画面就表示启动成功了。

2.3 安装 redis的可视化工具 redis desktop manager
https://redisdesktop.com/ 去这个地址来安装,很烦,下载的版本要付费,免费的要自己编译,它有教你如何编译的。要下载qt来编译。我下载qt编译了,但是不知道如何发布,所以也没法给下载地址。
3.改写原spider步骤
3.1 改spider
import scrapy from scrapy_redis.spiders import RedisSpider from tutorial.items import TutorialItem class QuotesSpider(RedisSpider): name = "quotes" redis_key = 'quotes:start_urls' # __init__方法必须按规定写,使用时只需要修改super()里的类名参数即可 def __init__(self, *args, **kwargs): # 修改这里的类名为当前类名 super(QuotesSpider, self).__init__(*args, **kwargs) def parse(self, response): item = TutorialItem() for quote in response.css('div.quote'): item['body'] = quote.css('span.text::text').extract_first() item['author'] = quote.css('small.author::text').extract_first() yield item next_page = response.css('li.next a::attr("href")').extract_first() if next_page is not None: yield response.follow(next_page, self.parse)
首先是改成继承RedisSpider,然后增加一个redis_key是爬虫名字加冒号加start_urls,这个等下会通过命令行手动push到redis数据库中的。去掉了start_requests,因为所有的爬虫都是从redis来获取url,所以没有开始请求的地址了。第一个启动的爬虫是通过命令的方式来push url进去的。
3.2 改settings
3.2.1 主爬虫的settings
# Enables scheduling storing requests queue in redis. SCHEDULER = "scrapy_redis.scheduler.Scheduler" # Ensure all spiders share same duplicates filter through redis. DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" SCHEDULER_PERSIST = True FEED_EXPORT_ENCODING = 'utf-8' ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 300, } REDIS_HOST = 'localhost' REDIS_PARAMS = { 'password': '123456', } REDIS_PORT = 6379
过滤的改成scrapy-redis 中的过滤类,还有scheduler也是。然后修改编码,再是pipeline也改成用redispipeline, 接下来如果是host的爬虫,就是主爬虫,要写REDIS_HOST的地址,下面的是密码和端口。注意下这里加上了密码,这样可以让其他的爬虫来连接安全些,不然又会提示其他的很烦。用密码的方式来启动redis的方法是:新建一个文件redis.conf,里面写
protected-mode no
requirepass 123456
123456就是redis的密码
然后用这样的方式来启动redis就是要密码了,
redis-server ./redis.conf
命令带上配置文本
3.2.2 子爬虫的settings
REDIS_URL = 'redis://root:123456@192.168.0.103:6379' REDIS_PORT = 6379
除了主爬虫外,其他的爬虫设置,其中redis filter pipeline等是和主爬虫一样,除了地址这个,是要访问主机的redis,所以要加用户名,密码,地址的方式.而不是REDIS_HOST了,用REDIS_URL的方式作为通信地址.
4.启动分布式抓取
4.1启动主爬虫
首先是主爬虫还是一样
scrapy crawl quotes
quotes 就是爬虫的名字,启动完了后,它是不会立即去抓的,因为还没有start_urls,再打开一个终端,输入
redis-cli auth 123456 lpush quotes:start_urls http://quotes.toscrape.com/tag/humor/
这样就OK了。 redis-cli表示启动redis客户端, auth后面的是redis密码。lpush是redis list的操作方式,往quotes:start_urls里面插入数据。爬虫会以这个作为启动url,然后爬完会删除,所以你通过redis可视化工具也不是马上能看到,因为它很快就删除了。
4.2启动子爬虫
scrapy crawl quotes
子爬虫就什么都不需要做了,它会连接上主机的redis,对那里的url进行处理。它自己爬到item也会插入到主机中的redis数据库中。
2027