scrapy-redis

本文介绍了Scrapy-Redis,一个扩展Scrapy框架的工具,支持分布式爬取、Redis任务调度、去重和增量爬取。讲解了如何将Scrapy项目转换为使用Redis的分布式爬虫,以及配置文件中涉及的关键设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是scrapy-redis

Scrapy-Redis 是 Scrapy 框架的一个扩展,它提供了对 Redis 数据库的支持,用于实现分布式爬取。通过使用 Scrapy-Redis,你可以将多个 Scrapy 进程连接到同一个 Redis 服务器,共享任务队列和去重集,从而实现爬虫的分布式调度。

  1. 主要特点和功能包括:
  1. 分布式爬取支持: Scrapy-Redis 允许多个 Scrapy进程协同工作,它们可以在不同的机器上运行,共享任务队列和去重集,提高爬取效率。

  2. 基于 Redis 的任务调度: 使用 Redis 作为任务队列,爬虫可以从中获取待爬取的URL,实现异步的、分布式的任务调度

  3. 基于 Redis 的去重: 利用 Redis 提供的集合数据结构,Scrapy-Redis 可以在分布式环境中进行URL去重,确保相同的URL在不同的爬虫进程中不会被重复爬取

  4. 支持增量爬取: 通过保存爬取状态,Scrapy-Redis 可以支持增量爬取,爬虫可以在上次中断的位置继续执行。

  5. 使用简单: Scrapy-Redis 尽量与原生的 Scrapy保持一致,使用起来相对简单,只需添加一些配置和稍微修改爬虫代码即可实现分布式爬取。

使用 Scrapy-Redis 需要安装对应的扩展,然后在 Scrapy 项目的配置文件中进行相应的设置,如配置 Redis 的地址和端口等。通过合理配置,Scrapy-Redis 可以使你的爬虫更适应大规模和分布式的爬取任务。

  1. 示意图:

在这里插入图片描述

二、将scrapy项目改造成scrapy-redis项目

  1. 步骤
  • 1.导入scraoy_redis模块中的分布式爬虫类RedisSpider
  • 2.继承该爬虫类
  • 3.注销start_urls 和allowed_domains
  • 4.设置redis_key以获取start_urls
  • 5.设置__init__获取允许的域
  • 6.编写配置文件
  1. 例子:

普通爬虫文件:

import scrapy
class BaiduSpider(scrapy.Spider):
    name = "baidu"
    allowed_domains = ["baidu.com"]
    start_urls = ["http://baidu.com/","http://baidu1.com/"]

    def parse(self, response):
        # 在这里处理初始页面的响应
        title = response.css('h1::text').get()
        self.log(f'Title on page {response.url}: {title}')

        # 提取页面中的链接并继续爬取
        links = response.css('a::attr(href)').getall()
        for link in links:
            yield scrapy.Request(url=link, callback=self.parse_link)

    def parse_link(self, response):
        # 在这里处理链接页面的响应
        title = response.css('h1::text').get()
        self.log(f'Title on linked page {response.url}: {title}')

        # 提取链接页面中的更多链接并继续爬取
        more_links = response.css('a::attr(href)').getall()
        for more_link in more_links:
            # 使用 yield 关键字将请求对象输出,使其成为一个生成器。
            # 这样做的目的是让 Scrapy 异步执行这个请求,允许爬虫同时处理多个请求,提高爬取效率
            yield scrapy.Request(url=more_link, callback=self.parse_link)

改造后的文件

#将普通spider文件改为分布式spider的步骤
# 1.导入scraoy_redis中的分布式爬虫类RedisSpider
# 2.继承该爬虫类
# 3.注销start_urls 和allowed_domains
# 4.设置redis_key以获取start_urls
# 5.设置__init__获取允许的域
# 6.编写配置文件
from scrapy_redis.spiders import RedisSpider
class MyRedisSpider(RedisSpider):
    name='baidu'
    redis_key = 'baidu_spider:start_urls'

    def __init__(self,*arge,**kwargs):
        # 动态定义允许的domain list(启动时传参数,可传可不传)
        # scrapy runspider baidu.py -a domain=example.com,example2.com
        # 注意 runspider用于启动一个py文件的爬虫,而crawl则可以启动项目路径下的多个爬虫
        domain = kwargs.pop('domain','')

        # 如果你不传 'domain' 参数启动爬虫,它仍然可以正常运行
        # 只是 self.allowed_domains 将被设置为一个空列表,这意味着爬虫会爬取所有域名
        self.allowed_domains=list(filter(None,domain.split(',')))
        super(MyRedisSpider,self).__init__(*arge,**kwargs)


    def parse(self, response):
        title = response.css('h1::text').get()
        self.log(f'Title on page {response.url}: {title}')

        links = response.css('a::attr(href)').getall()
        for link in links:
            # 使用 yield self.make_request_from_data(link) 代替 scrapy.Request
            yield self.make_request_from_data(link)

    def parse_link(self, response):
        title = response.css('h1::text').get()
        self.log(f'Title on linked page {response.url}: {title}')

        more_links = response.css('a::attr(href)').getall()
        for more_link in more_links:
            # 使用 yield self.make_request_from_data(more_link) 代替 scrapy.Request
            yield self.make_request_from_data(more_link)

  • 注意 runspider用于启动一个py文件的爬虫,而crawl则可以启动项目路径下的多个爬虫

三、配置文件

#Resis 设置

#使能Redis调度器

SCHEDULER = 'scrapy_redis.scheduler.Scheduler'

#所有spider通过redis使用同一个去重过滤器

DUPEFILTER_CLASS  = 'scrapy_redis.dupefilter.RFPDupeFilter'

#不清除Redis队列、这样可以暂停/恢复 爬取

#SCHEDULER_PERSIST = True

#SCHEDULER_QUEUE_CLASS ='scrapy_redis.queue.PriorityQueue' #默认队列,优先级队列
#备用队列。
#SCHEDULER_QUEUE_CLASS ='scrapy_redis.queue.FifoQueue'  #先进先出队列
#SCHEDULER_QUEUE_CLASS ='scrapy_redis.queue.LifoQueue'  #后进先出队列

#最大空闲时间防止分布式爬虫因为等待而关闭

#SCHEDULER_IDLE_BEFORE_CLOSE = 10


#将抓取的item存储在Redis中以进行后续处理。

ITEM_PIPELINES  = {
     'scrapy_redis.pipelines.RedisPipeline':300,
}

# The item pipeline serializes and stores the items in this redis key.
#item pipeline 将items 序列化 并用如下key名储存在redis中

#REDIS_ITEMS_KEY = '%(spider)s:items'

#默认的item序列化方法是ScrapyJSONEncoder,你也可以使用自定义的序列化方式

#REDIS_ITEMS_SERIALIZER = 'json.dumps'


#设置redis地址 端口 密码

REDIS_HOST = 'localhost'
REDIS_HOST = 6379

#也可以通过下面这种方法设置redis地址 端口和密码,一旦设置了这个,则会覆盖上面所设置的REDIS_HOST和REDIS_HOST

 REDIS_URL = 'redis://root:redis_pass@xxx.xx.xx.xx:6379'  
 #root用户名,redis_pass:你设置的redis验证密码,xxxx:你的主机ip

#你设置的redis其他参数 Custom redis client parameters (i.e.: socket timeout, etc.)
REDIS_PARAMS  = {}


#自定义的redis客户端类
#REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'

# If True, it uses redis ``zrevrange`` and ``zremrangebyrank`` operation. You have to use the ``zadd``
# command to add URLS and Scores to redis queue. This could be useful if you
# want to use priority and avoid duplicates in your start urls list.

#REDIS_START_URLS_AS_SET = False

# 默认的RedisSpider 或 RedisCrawlSpider  start urls key

#REDIS_START_URLS_KEY = '%(name)s:start_urls'

#redis的默认encoding是utf-8,如果你想用其他编码可以进行如下设置:

#REDIS_ENCODING = 'latin1'

### Scrapy-Redis 使用与配置 Scrapy-Redis 是一个基于 Redis 的扩展,用于实现分布式爬取。它通过将 Scrapy 的调度器和去重机制移至 Redis 中,允许多个 Scrapy 实例共享同一个爬取队列,从而避免重复爬取并提高效率[^1]。 #### 安装依赖 在使用 Scrapy-Redis 之前,需要安装必要的依赖库。可以通过以下命令安装: ```bash pip install scrapy-redis ``` 此命令会安装 ScrapyRedis 相关的依赖包,确保环境准备就绪[^1]。 #### 配置调度器和去重机制 为了启用 Scrapy-Redis 的分布式功能,需要在项目的 `settings.py` 文件中进行如下配置: 1. **替换调度器类**:将默认的调度器替换为 Scrapy-Redis 提供的调度器。 ```python SCHEDULER = "scrapy_redis.scheduler.Scheduler" ``` 2. **启用持久化功能**:设置是否在关闭爬虫时保留调度器中的请求队列。 ```python SCHEDULER_PERSIST = True ``` 3. **替换去重过滤器类**:将默认的去重过滤器替换为 Scrapy-Redis 提供的去重过滤器。 ```python DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" ``` 这些配置确保 Scrapy 使用 Redis 来管理请求队列和去重记录[^2]。 #### Redis 连接配置 为了连接到 Redis 服务器,可以在 `settings.py` 中添加 Redis 的连接参数: ```python REDIS_HOST = 'localhost' REDIS_PORT = 6379 ``` 如果需要密码认证,可以添加以下配置: ```python REDIS_PASSWORD = 'your_redis_password' ``` 这些参数定义了 Scrapy 如何连接到 Redis 服务器,确保数据能够在多个爬虫实例之间共享[^2]。 #### 分布式爬虫优化 在高并发环境下,分布式爬虫可能面临一些挑战。为了保证数据采集的实时性和完整性,可以采取以下措施: - **代理 IP 技术**:通过轮换代理 IP,减少因频繁访问同一 IP 被目标网站封禁的风险。 - **Cookie 和 User-Agent 设置**:合理配置 Cookie 和 User-Agent,模拟真实用户行为,降低被检测的概率。 - **请求速率控制**:通过 `DOWNLOAD_DELAY` 和 `CONCURRENT_REQUESTS` 参数,调整爬取速度以适应目标网站的要求[^3]。 ```python # 示例:设置下载延迟和并发请求数 DOWNLOAD_DELAY = 1 CONCURRENT_REQUESTS = 16 ``` #### 示例代码 以下是一个简单的 Scrapy-Redis 项目配置示例: ```python # settings.py BOT_NAME = 'example' SPIDER_MODULES = ['example.spiders'] NEWSPIDER_MODULE = 'example.spiders' # Scrapy-Redis 配置 SCHEDULER = "scrapy_redis.scheduler.Scheduler" DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" SCHEDULER_PERSIST = True # Redis 连接配置 REDIS_HOST = 'localhost' REDIS_PORT = 6379 ``` 通过上述配置,Scrapy-Redis 可以实现高效的分布式爬取,并结合其他技术手段提升抓取效果[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值