Scrapy-Redis Scheduler 队列模式详解
scrapy-redis 的 Scheduler 支持三种队列模式,底层分别对应不同的 Redis 数据结构: 特点: 基于 Redis ZADD/ZPOPMIN,以 Request 的 适用场景: 注意: ZADD 时间复杂度为 O(log N),数据量极大时性能略低于纯 List 操作。 特点: 按照 URL 发现顺序依次处理,类似广度优先搜索(BFS)。 适用场景: 特点: 最新入队的请求先被处理,类似深度优先搜索(DFS)。 适用场景: 在 在 Spider 中,通过 大多数项目用默认的 PriorityQueue 配合 Scrapy-Redis Scheduler 队列模式详解
学习日期:2026-02-24
关键词:scrapy-redis、Scheduler、队列、优先级、BFS、DFS一、三种队列模式概览
队列类型 Redis 结构 类路径 默认? 优先级队列 Sorted Set (ZSET) scrapy_redis.queue.PriorityQueue✅ 是 先进先出(FIFO) List(LPUSH/RPOP) scrapy_redis.queue.FifoQueue否 先进后出(LIFO/栈) List(LPUSH/LPOP) scrapy_redis.queue.LifoQueue否 二、各队列特点与使用场景
1. 优先级队列(PriorityQueue)— 默认
priority 字段作为排序依据,priority 越大越先处理。2. 先进先出(FifoQueue)— BFS 广度优先
3. 先进后出(LifoQueue)— DFS 深度优先
三、如何配置队列模式
settings.py 中指定:SCHEDULER = 'scrapy_redis.scheduler.Scheduler'
DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
# 三选一,默认为 PriorityQueue
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
# SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
# SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'
REDIS_URL = 'redis://localhost:6379'四、优先级队列的原理与使用
4.1 底层实现原理
yield Request(priority=10)
↓
Scheduler.enqueue_request()
↓
PriorityQueue.push()
↓
Redis: ZADD key score=-10 value=序列化的Request
(存入时对 priority 取负数作为 score)
↓
取出时: ZPOPMIN → 取 score 最小值 = priority 最大的请求关键点: scrapy-redis 在存入 ZSET 时自动将 priority 取负数作为 score,因此你只需记住:
priority 正数越大 = 越先被处理,框架自动处理转换。4.2 设置 Request 优先级
scrapy.Request 的 priority 参数指定:# 高优先级
yield scrapy.Request(url, callback=self.parse_detail, priority=10)
# 中优先级
yield scrapy.Request(url, callback=self.parse_category, priority=5)
# 低优先级
yield scrapy.Request(url, callback=self.parse, priority=1)4.3 完整示例:电商爬虫按优先级抓取
# spiders/shop_spider.py
import scrapy
from scrapy_redis.spiders import RedisSpider
class ShopSpider(RedisSpider):
name = 'shop'
redis_key = 'shop:start_urls'
def parse(self, response):
# 商品详情页 → 最高优先级(最想要的数据)
for product_url in response.css('a.product-link::attr(href)').getall():
yield scrapy.Request(
url=response.urljoin(product_url),
callback=self.parse_product,
priority=10
)
# 分类列表页 → 中等优先级
for category_url in response.css('a.category::attr(href)').getall():
yield scrapy.Request(
url=response.urljoin(category_url),
callback=self.parse_category,
priority=5
)
# 翻页链接 → 低优先级
next_page = response.css('a.next-page::attr(href)').get()
if next_page:
yield scrapy.Request(
url=response.urljoin(next_page),
callback=self.parse,
priority=1
)
def parse_product(self, response):
yield {
'title': response.css('h1::text').get(),
'price': response.css('.price::text').get(),
}4.4 在 Redis 中验证优先级
# 查看队列中所有请求及其 score(score 越小 = 优先级越高)
ZRANGE shop:requests 0 -1 WITHSCORES
# 预期结果示例:
# 序列化的Request(详情页) score: -10
# 序列化的Request(分类页) score: -5
# 序列化的Request(翻页) score: -1五、选择建议
需要控制不同类型 URL 的抓取顺序 → PriorityQueue(默认,推荐)
追求广度覆盖 / 按层级均匀抓取 → FifoQueue
追求深度 / 快速完成某条内容链路 → LifoQueuepriority 参数即可满足需求,只有在明确需要 BFS/DFS 语义时才切换其他两种模式。






















