Scrapy-Redis分布式爬虫重复爬取已抓取URL问题求助
问题原因分析
1. 调度器持久化配置缺失导致去重集合被清空
Scrapy-Redis默认SCHEDULER_PERSIST = False,当第一个爬虫节点完成所有任务并关闭时,会自动清空Redis中的去重指纹集合和任务队列。如果第二个节点此时仍在运行,它会因为去重集合被清空,无法识别已爬取的URL,进而重复请求这些URL;同时,由于队列被清空后,第二个节点可能没有及时检测到队列空状态,导致无法触发max_idle_time的关闭逻辑。
2. 任务批量获取与空闲时间的配合问题
你设置了redis_batch_size = 1,每个节点每次仅从Redis获取1个URL。当队列只剩最后1个URL时,第一个节点取走并处理完成后,队列变为空。第二个节点在尝试获取URL时,可能因为Redis的网络延迟,没有立即检测到队列空,导致在max_idle_time周期内重复发起获取请求;如果此时去重集合已被第一个节点清空,它就会重新请求已爬过的URL。
3. 多节点文件写入冲突导致进程无法正常退出
两个爬虫节点同时向同一个distributed_scrape_data.json文件写入数据,且设置了overwrite: True。这种情况下,可能出现文件锁冲突:第一个节点关闭时覆盖了文件,第二个节点的写入操作被阻塞,导致爬虫进程无法正常触发关闭逻辑,进而进入循环状态,重复处理已有的任务数据。
解决方案建议
- 开启调度器持久化:在
settings.py中添加SCHEDULER_PERSIST = True,这样爬虫节点关闭时不会清空Redis中的去重集合和队列,确保所有节点共享一致的去重状态。 - 调整批量获取大小:适当增大
redis_batch_size(比如设置为5或10),减少节点频繁从Redis获取URL的次数,降低网络延迟带来的状态不同步问题。 - 避免多节点写入同一文件:将FEEDS配置改为按节点生成独立文件,比如:
或者使用Redis等共享存储汇总数据后统一导出。import os # ... custom_settings = { 'FEEDS': { f'distributed_scrape_data_{os.getpid()}.json': {'format': 'json', 'overwrite': True}, }, } - 检查Redis连接稳定性:确保所有爬虫节点与Redis服务器的连接稳定,避免因连接波动导致的状态同步延迟。
内容的提问来源于stack exchange,提问作者cuong nguyen
相关产品推荐
相关产品推荐

