scrapy本身不支持分布式,必须通过scrapy-redis替换调度器和去重器,共用redis实现协同;核心配置缺一不可:dupefilter_class、scheduler、scheduler_persist、redis_url,爬虫须继承redisspider并手动向redis推送起始url。

Scrapy 本身不支持分布式,硬配 scrapy crawl 多实例只会撞库、重复抓、去重失效——这不是分布式,是并发灾难。
必须用 scrapy-redis 替换调度器和去重器,所有节点共享同一个 Redis 实例,才能实现真正协同。
settings.py 必须改的四个配置项
只改这四条,缺一不可,顺序无关但必须共存:
-
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter":把内存去重换成 Redis Set -
SCHEDULER = "scrapy_redis.scheduler.Scheduler":用 Redis List/Queue 替代内存优先队列 -
SCHEDULER_PERSIST = True:关爬虫也不清空队列,否则重启后任务丢失 -
REDIS_URL = "redis://127.0.0.1:6379":所有节点指向同一地址,密码需写成redis://:mypass@host:port
别漏掉 SCHEDULER_PERSIST——设为 False(默认值)会导致每次 Ctrl+C 后队列清空,新启动的实例直接退出。
起始 URL 必须手动推入 Redis,不能靠 start_urls
scrapy-redis 不读取爬虫类里的 start_urls,它只监听 Redis 中指定 key 的 list。常见错误是改完配置就直接 scrapy crawl myspider,结果没日志、没请求、进程秒退。
- 先确认
redis-cli ping返回PONG - 执行:
redis-cli lpush myspider:start_urls "https://example.com"(key 名要和爬虫中redis_key一致) - 再启动任意数量的实例:
scrapy crawl myspider
注意:如果用了自定义 REDIS_START_URLS_KEY,那 push 的 key 得跟着变;没配就默认用 {spider_name}:start_urls。
爬虫类必须继承 RedisSpider,不是普通 Spider
普通 scrapy.Spider 会忽略 Redis 队列,永远不消费任务。必须显式继承 scrapy_redis.spiders.RedisSpider:
from scrapy_redis.spiders import RedisSpider
<p>class MySpider(RedisSpider):
name = 'myspider'
redis_key = 'myspider:start_urls' # 和 lpush 的 key 完全一致</p><pre class="brush:python;toolbar:false;">def parse(self, response):
yield {'url': response.url}
for href in response.css('a::attr(href)').getall():
yield response.follow(href, self.parse)
这个 redis_key 是唯一入口,start_urls 属性完全无效。如果误写成 RedisCrawlSpider 或漏掉 redis_key,实例启动后立即 idle 退出。
去重粒度影响性能和准确性,别盲目用默认 fingerprint
scrapy-redis 默认用完整 Request 对象生成指纹(含 method、body、headers、cookies),安全但慢。如果业务只需 URL 去重(比如全是 GET),可简化逻辑避免序列化开销:
import hashlib from scrapy_redis.dupefilter import RFPDupeFilter <p>class UrlOnlyDupeFilter(RFPDupeFilter): def request_fingerprint(self, request): return hashlib.sha1(request.url.encode()).hexdigest()</p>
然后在 settings.py 中替换:DUPEFILTER_CLASS = "myproject.dupefilters.UrlOnlyDupeFilter"。但要注意:这样会把带不同 body 的 POST 请求、或同 URL 不同 Cookie 的请求当成重复——得自己权衡。
真实部署时,最容易被忽略的是 Redis 连接稳定性与超时配置。没设 REDIS_PARAMS 里的 socket_timeout 和 retry_on_timeout,网络抖动时爬虫会卡死或静默失败,而不是报错重试。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











