使用 Scrapy-Redis 进行分布式爬取

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,看下下面的画面就表示启动成功了。

使用 Scrapy-Redis 进行分布式爬取_第1张图片
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:[email protected]: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数据库中。

 

http://www.waitingfy.com/archives/2027

你可能感兴趣的:(scrapy)