分布式爬虫实战:Scrapy-Redis 详解
目录
分布式爬虫实战:Scrapy-Redis 详解
📚 前置知识
本配方涉及以下核心技术,建议先阅读相关章节:
- Scrapy 快速入门 - 理解 Scrapy 调度器与去重机制
- Redis 基础 - 掌握 Redis 列表、集合操作
Scrapy 默认是单机架构,请求队列保存在内存中,重启即失,且无法多机共享。Scrapy-Redis 是一个强大的组件,它重写了 Scrapy 的调度器 (Scheduler) 和去重组件 (DupeFilter),将请求队列和指纹集合存储在 Redis 中,从而实现:
- 分布式爬取: 多个爬虫节点共享同一个 Redis 队列,协同工作。
- 断点续爬: 请求持久化在 Redis 中,爬虫挂掉重启后可继续运行。
1. 核心架构原理
原生 Scrapy vs Scrapy-Redis
原生 Scrapy:
- Scheduler: 维护在内存中的 Python
deque或queue。 - DupeFilter: 维护在内存中的 Python
set。 - 缺点: 无法跨进程/跨机器共享,内存受限。
Scrapy-Redis:
- Scheduler: 从 Redis 的
List(或PriorityQueue) 中POP请求,向其PUSH新请求。 - DupeFilter: 利用 Redis 的
Set数据结构存储 URL 指纹 (SHA1),利用 Redis 的原子性进行去重。 - Item Pipeline: 可选将提取的数据直接推入 Redis,由独立的 Worker 消费存储。
2. 环境搭建与配置
安装
| |
配置 settings.py
| |
3. 编写分布式 Spider
继承 RedisSpider
| |
启动流程
- 启动爬虫(多个终端启动多个实例):
1scrapy crawl myspider_distributed - 向 Redis 推送起始 URL:
1redis-cli lpush myspider:start_urls http://example.com
使用 RedisCrawlSpider
如果你需要利用 Rule 和 LinkExtractor 自动抓取全站,可以使用 RedisCrawlSpider。
| |
4. 进阶优化策略
Bloom Filter 去重优化
Scrapy-Redis 默认使用 Redis Set 存储所有指纹。对于亿级 URL 的爬取,这会消耗数十 GB 内存。解决方案是集成 Bloom Filter。
实现思路:
- 重写
RFPDupeFilter。 - 使用
redis-py的bf.add和bf.exists命令 (需要 RedisBloom 模块) 或 Python 端的pybloom_live映射到 Redis BitMap。
| |
请求优先级
| |
空闲超时关闭
| |
5. 部署架构图
graph TB
subgraph "Master / Redis Server"
Redis[(Redis Queue & Set)]
end
subgraph "Slave 1"
Spider1[Scrapy Spider 1] -->|Pop Request| Redis
Spider1 -->|Push Request| Redis
Spider1 -->|Dupe Check| Redis
end
subgraph "Slave 2"
Spider2[Scrapy Spider 2] -->|Pop Request| Redis
Spider2 -->|Push Request| Redis
Spider2 -->|Dupe Check| Redis
end
subgraph "Data Storage"
Mongo[(MongoDB)]
end
Spider1 -->|Store Item| Mongo
Spider2 -->|Store Item| Mongograph TB
subgraph "Master / Redis Server"
Redis[(Redis Queue & Set)]
end
subgraph "Slave 1"
Spider1[Scrapy Spider 1] -->|Pop Request| Redis
Spider1 -->|Push Request| Redis
Spider1 -->|Dupe Check| Redis
end
subgraph "Slave 2"
Spider2[Scrapy Spider 2] -->|Pop Request| Redis
Spider2 -->|Push Request| Redis
Spider2 -->|Dupe Check| Redis
end
subgraph "Data Storage"
Mongo[(MongoDB)]
end
Spider1 -->|Store Item| Mongo
Spider2 -->|Store Item| Mongograph TB
subgraph "Master / Redis Server"
Redis[(Redis Queue & Set)]
end
subgraph "Slave 1"
Spider1[Scrapy Spider 1] -->|Pop Request| Redis
Spider1 -->|Push Request| Redis
Spider1 -->|Dupe Check| Redis
end
subgraph "Slave 2"
Spider2[Scrapy Spider 2] -->|Pop Request| Redis
Spider2 -->|Push Request| Redis
Spider2 -->|Dupe Check| Redis
end
subgraph "Data Storage"
Mongo[(MongoDB)]
end
Spider1 -->|Store Item| Mongo
Spider2 -->|Store Item| Mongograph TB
subgraph "Master / Redis Server"
Redis[(Redis Queue & Set)]
end
subgraph "Slave 1"
Spider1[Scrapy Spider 1] -->|Pop Request| Redis
Spider1 -->|Push Request| Redis
Spider1 -->|Dupe Check| Redis
end
subgraph "Slave 2"
Spider2[Scrapy Spider 2] -->|Pop Request| Redis
Spider2 -->|Push Request| Redis
Spider2 -->|Dupe Check| Redis
end
subgraph "Data Storage"
Mongo[(MongoDB)]
end
Spider1 -->|Store Item| Mongo
Spider2 -->|Store Item| Mongo6. 常见问题
Q: 爬虫启动后一直等待,不抓取?
A: 确认已向 redis_key 推送了起始 URL:
| |
Q: 如何监控爬取进度?
A: 使用 Redis 命令查看队列长度:
| |
Q: 如何清空队列重新开始?
A: 删除 Redis 中的相关键:
| |
总结
Scrapy-Redis 是构建分布式爬虫系统的核心组件。通过将调度器和去重组件迁移到 Redis,实现了多节点协同爬取和断点续爬能力,是大规模数据采集的必备工具。
相关内容
如果这篇文章对你有帮助,请我喝杯咖啡吧~
支付宝
微信