scrapy_redis

一:scrapy_redis 的概念和作用

1. 分布式是什么

简单的说 分布式就是不同的节点(服务器,ip不同)共同完成一个任务

2. scrapy_redis的概念

scrapy_redis是scrapy框架的基于redis的分布式组件

3. scrapy_redis的作用

Scrapy_redis在scrapy的基础上实现了更多,更强大的功能,具体体现在:

通过持久化请求队列和请求的指纹集合来实现:

  • 断点续爬

  • 分布式快速抓取

 

4 scrapy_redis的流程

  • 在scrapy_redis中,所有的待抓取的request对象和去重的request对象指纹都存在所有的服务器公用的redis中

  • 所有的服务器中的scrapy进程公用同一个redis中的request对象的队列

  • 所有的request对象存入redis前,都会通过该redis中的request指纹集合进行判断,之前是否已经存入过

  • 在默认情况下所有的数据会保存在redis中

具体流程如下:

 

 

二:scrapy_redis原理分析并实现断点续爬以及分布式爬虫

1. 下载github的demo代码

  1. clone github scrapy-redis源码文件

    git clone https://github.com/rolando/scrapy-redis.git

  2. 研究项目自带的demo

    mv scrapy-redis/example-project ~/scrapyredis-project

 

2. 观察dmoz文件

在domz爬虫文件中,实现方式就是之前的crawlspider类型的爬虫

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class DmozSpider(CrawlSpider):
    """Follow categories and extract links."""
    name = 'dmoz'
    allowed_domains = ['dmoz-odp.org']
    start_urls = ['http://www.dmoz-odp.org/']

    rules = [
        Rule(LinkExtractor(
            restrict_css=('.top-cat', '.sub-cat', '.cat-item')
        ), callback='parse_directory', follow=True),
    ]

    def parse_directory(self, response):
        for div in response.css('.title-and-desc'):
            yield {
                'name': div.css('.site-title::text').extract_first(),
                'description': div.css('.site-descr::text').extract_first().strip(),
                'link': div.css('a::attr(href)').extract_first(),
            }

 

但是在settings.py中多了以下内容,这几行表示scrapy_redis中重新实现的了去重的类,以及调度器,并且使用RedisPipeline管道类

#设置重复重复过滤器的模块
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

#设置调度器,scrapy_redis中的调度器具备与数据库的交互功能 SCHEDULER = "scrapy_redis.scheduler.Scheduler"

#设置当爬虫结束的时候是否保持redis数据库中的去重集合与任务队列
SCHEDULER_PERSIST = True ITEM_PIPELINES = { 'example.pipelines.ExamplePipeline': 300,
   #当开启该管道,该管道会把数据存到redis数据库中
'scrapy_redis.pipelines.RedisPipeline': 400, }

 

3. 运行dmoz爬虫,观察现象

1:首先我们需要添加redis的地址,程序才能够使用redis

REDIS_URL = "redis://127.0.0.1:6379"
#或者使用下面的方式
# REDIS_HOST = "127.0.0.1"
# REDIS_PORT = 6379

2:我们执行domz的爬虫,会发现redis中多了一下三个键:

 

 

 

3:中止进程后再次运行dmoz爬虫继续执行程序,会发现程序在前一次的基础之上继续往后执行,所以domz爬虫是一个基于url地址的增量式的爬虫

 

 

4. scrapy_redis的原理分析

我们从settings.py中的三个配置来进行分析分别是:

  • RedisPipeline # 管道类

  • RFPDupeFilter # 指纹去重类

  • Scheduler # 调度器类

  • SCHEDULER_PERSIST # 是否持久化请求队列和指纹集合

4.1 Scrapy_redis之RedisPipeline

RedisPipeline中观察process_item,进行数据的保存,存入了redis中

1:配置项

 

2:查找位置

 

 

 3:原理

 

 

4.2 Scrapy_redis之RFPDupeFilter

RFPDupeFilter 实现了对request对象的加密

1:位置

 

 2:源码分析

 

 

4.3 Scrapy_redis之Scheduler

scrapy_redis调度器的实现了决定什么时候把request对象加入带抓取的队列,同时把请求过的request对象过滤掉

 

 

5. 实现分布式爬虫

5.1 分析demo中代码

打开example-project项目中的myspider_redis.py文件

通过观察代码:

  1. 继承自父类为RedisSpider

  2. 增加了一个redis_key的键,没有start_urls,因为分布式中,如果每台电脑都请求一次start_url就会重复

  3. 多了__init__方法,该方法不是必须的,可以手动指定allow_domains

  4. 启动方法:

    1. 在每个节点正确的目录下执行scrapy crawl 爬虫名,使该节点的scrapy_redis爬虫程序就位

    2. 在共用的redis中 lpush redis_key 'start_url',使全部节点真正的开始运行

  5. settings.py中关键的配置

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True
​
ITEM_PIPELINES = {
    'example.pipelines.ExamplePipeline': 300,
    'scrapy_redis.pipelines.RedisPipeline': 400,
}
REDIS_URL = "redis://127.0.0.1:6379"

 

 

5.2 动手实现分布式爬虫

改写tencent爬虫为分布式爬虫

注意:启动方式发生改变

5.3编写流程

 

posted on 2020-12-12 11:29  paike123  阅读(414)  评论(0)    收藏  举报

导航