Scrapy 是一个用 Python 编写的高性能、可扩展的开源网络爬虫框架

📅 2026/7/12 0:14:12
Scrapy 是一个用 Python 编写的高性能、可扩展的开源网络爬虫框架
Scrapy 是一个用 Python 编写的高性能、可扩展的开源网络爬虫框架原生设计为单机架构不直接支持分布式爬虫。但通过结合外部组件如 Redis、RabbitMQ、Kafka 等可构建分布式爬虫系统常见方案包括✅Scrapy-Redis最经典基于 Redis 实现请求队列SpiderQueue/PriorityQueue、去重集合DupeFilter和指纹存储多个 Scrapy 爬虫实例共享同一 Redis 数据库实现任务分发与状态同步需重写Scheduler、DupeFilter和ItemPipeline继承scrapy_redis.spiders.RedisSpider。✅Scrapy Redis 自定义调度器利用 Redis 的LPUSH/BRPOP实现任务队列使用scrapy-redis提供的中间件或自行开发RedisScheduler支持动态添加起始 URL通过lpush myspider:start_urls http://xxx。⚠️ 注意事项Scrapy 本身无内置分布式协调机制如节点发现、故障转移、负载均衡需依赖外部服务去重需统一使用 Redis 的set或bloom filter如scrapy-redis-bloom避免重复抓取Item 存储建议统一写入数据库MySQL/PostgreSQL或消息队列Kafka避免多实例写冲突日志、监控、限速策略需集中管理如 Prometheus Grafana ELK。 示例Scrapy-Redis 快速启动pipinstallscrapy-redis在settings.py中配置SCHEDULERscrapy_redis.scheduler.SchedulerDUPEFILTER_CLASSscrapy_redis.dupefilter.RFPDupeFilterREDIS_URLredis://localhost:6379继承RedisSpiderimportscrapyfromscrapy_redis.spidersimportRedisSpiderclassMySpider(RedisSpider):namemyspiderredis_keymyspider:start_urlsdefparse(self,response):yield{url:response.url,title:response.css(title::text).get()}启动多个实例后向 Redis 推送 URL 即可触发分布式抓取。Scrapy-Redis 的去重机制核心是将 Scrapy 原生的本地RFPDupeFilter基于scrapy.utils.request.request_fingerprint迁移到 Redis 中持久化存储从而实现多爬虫实例共享同一去重集合。其本质不是重新设计指纹算法而是复用 Scrapy 的指纹逻辑 分布式存储层。✅指纹生成逻辑与本地完全一致Scrapy-Redis 使用scrapy.utils.request.request_fingerprint()生成请求指纹fingerprint该函数默认行为为对请求的method、url、body、headers仅含标准化后的关键头如User-Agent、Cookie等取决于DUPEFILTER_DEBUG和HTTPCACHE_IGNORE_HEADERS配置、cookies等字段进行规范化如 URL 去参数顺序、body 排序、headers 小写归一化序列化后经 SHA1 哈希生成长度为 40 的十六进制字符串如a1b2c3...✅该指纹算法与 Scrapy 默认RFPDupeFilter完全相同保证语义一致性——同一请求在单机或分布式环境下生成的指纹绝对一致。✅去重存储与判断流程分布式关键差异环节本地RFPDupeFilterScrapy-RedisRFPDupeFilter存储介质Pythonset()内存进程级RedisSET或Bloom Filter如scrapy-redis-bloom去重范围单个爬虫进程内所有连接同一 Redis 的爬虫实例全局共享判断方式fingerprint in self.fingerprintsSISMEMBER dupefilter:myspider fingerprint原子操作持久化进程退出即丢失Redis 持久化RDB/AOF可长期保留去重记录扩展性无法跨实例共享支持无限水平扩展爬虫节点可选增强Bloom Filter 替代 SET为节省内存尤其海量 URL 场景可启用scrapy-redis-bloom使用 Redis 的bf.add/bf.exists需 RedisBloom 模块以极小概率误判false positive≈0.1% 可配置但不产生 false negative不会漏判重复内存占用仅为 SET 的 1/81/10适合亿级 URL 去重。⚠️ 注意事项若自定义Request并覆盖__hash__或__eq__需确保request_fingerprint()仍能正确反映语义唯一性DUPEFILTER_CLASS scrapy_redis.dupefilter.RFPDupeFilter是默认配置无需修改即可生效Redis 连接异常时RFPDupeFilter默认会抛出异常可捕获并降级为本地去重但需自行实现容错逻辑。