2026 Scrapy进阶实战:分布式爬虫架构设计+Redis队列应用

📅 发布时间:2026/7/6 12:43:29 👁️ 浏览次数:
2026 Scrapy进阶实战:分布式爬虫架构设计+Redis队列应用
最近做大数据采集的朋友找我吐槽“用Scrapy写的单机爬虫爬取千万级商品数据跑了3天还没爬完服务器CPU占满还经常被封IP”我笑着说“这事儿交给分布式爬虫啊用Scrapy-Redis做分布式架构Redis做任务队列和去重多台服务器同时爬取效率直接翻10倍还能自动负载均衡、断点续爬”今天就把这个Scrapy进阶实战教程分享给你——从单机爬虫改造为分布式架构核心讲解Redis队列的应用、去重机制、任务分发新手也能看懂附完整可运行的分布式爬虫代码Redis环境搭建步骤⚠️重要提醒必须先看本文仅供学习交流使用不要用于商业用途分布式爬虫爬取速度极快务必控制并发量遵守网站robots.txt和用户协议建议先掌握Scrapy基础比如Item、Pipeline、Middleware再学习分布式架构本文以爬取“豆瓣书籍TOP250”为例低反爬、数据规范新手易上手。一、核心概念分布式爬虫 vs 单机爬虫先搞懂核心区别避免新手走弯路特性单机Scrapy爬虫分布式Scrapy-Redis爬虫任务队列本地内存队列爬取中断丢失Redis分布式队列断点续爬去重机制本地集合多机重复爬取Redis集合全局唯一去重数据存储本地文件/数据库统一存储到中心数据库/文件并发能力受单台服务器性能限制多机集群并发量线性提升扩展性差只能升级单机配置好新增服务器即可扩容核心依赖ScrapyScrapy Redis Scrapy-Redis分布式爬虫核心原理一句话讲透多台爬虫服务器Slave连接同一个Redis服务器MasterRedis存储待爬取的URL队列redis_key、已爬取的URL去重集合Master分发任务Slave自动从Redis获取任务、执行爬取、提交结果实现多机协同爬取。二、准备工作环境搭建新手15分钟搞定1. 基础环境所有服务器都要装# 1. 安装Python建议3.8# 2. 安装Scrapy和Scrapy-Redis国内镜像源pipinstallscrapy scrapy-redis -i https://pypi.tuna.tsinghua.edu.cn/simple# 3. 安装Redis客户端pipinstallredis -i https://pypi.tuna.tsinghua.edu.cn/simple# 4. 验证安装scrapy version# 显示Scrapy版本即成功python -cimport scrapy_redis; print(scrapy_redis.__version__)# 显示版本即成功2. Redis服务器搭建核心只需要一台Master新手推荐用Docker快速搭建Redis不用手动配置# 1. 安装Docker以Ubuntu为例Windows/Mac直接装Docker Desktopsudoapt-getupdatesudoapt-getinstalldocker.io -y# 2. 拉取Redis镜像dockerpull redis:latest# 3. 启动Redis容器开放6379端口设置密码持久化数据dockerrun -d --name redis-master -p6379:6379\-v /data/redis:/data\redis:latest\redis-server --requirepass你的Redis密码--appendonlyyes# 4. 验证Redis是否启动成功dockerps# 看到redis-master容器状态为Up即成功redis-cli -h 你的Redis服务器IP -p6379-a 你的Redis密码# 连接成功即OK⚠️ 关键配置--requirepass设置Redis密码必须避免被恶意访问-v /data/redis:/data数据持久化到本地重启容器不丢失开放6379端口所有Slave服务器都能访问Master的6379端口。三、实战步骤从0搭建分布式爬虫步骤1创建Scrapy项目任意一台服务器都能创建# 创建项目scrapy startproject douban_books_distributed# 创建爬虫cddouban_books_distributed scrapy genspider douban_books book.douban.com步骤2核心改造分布式关键配置1. 修改settings.py最核心替换原有的settings.py内容我加了详细注释# Scrapy项目基本配置BOT_NAMEdouban_books_distributedSPIDER_MODULES[douban_books_distributed.spiders]NEWSPIDER_MODULEdouban_books_distributed.spidersROBOTSTXT_OBEYTrue# 遵守robots.txtDOWNLOAD_DELAY1# 下载延迟反爬关键# 分布式核心配置重点 # 1. 启用Scrapy-Redis的调度器替换默认本地调度器SCHEDULERscrapy_redis.scheduler.Scheduler# 2. 启用Scrapy-Redis的去重过滤器替换默认本地去重DUPEFILTER_CLASSscrapy_redis.dupefilter.RFPDupeFilter# 3. Redis连接配置替换成你的Redis服务器信息REDIS_HOST你的Redis服务器IP# 比如192.168.1.100REDIS_PORT6379REDIS_PARAMS{password:你的Redis密码,db:0# 使用第0个数据库}# 4. 任务队列的Redis Key所有Slave共用这个KeyREDIS_START_URLS_KEYdouban_books:start_urls# 5. 断点续爬爬虫中断后重启不会重新爬取已完成的任务SCHEDULER_PERSISTTrue# 6. 优先级队列可选默认按FIFO# SCHEDULER_QUEUE_CLASS scrapy_redis.queue.PriorityQueue# 爬虫并发配置根据服务器性能调整 CONCURRENT_REQUESTS16# 单爬虫并发数CONCURRENT_REQUESTS_PER_DOMAIN8# 单域名并发数CONCURRENT_REQUESTS_PER_IP4# 单IP并发数# 数据管道配置可选将数据存入Redis ITEM_PIPELINES{# 本地JSON管道单机测试用# douban_books_distributed.pipelines.DoubanBooksDistributedPipeline: 300,# Scrapy-Redis管道将Item存入Redisscrapy_redis.pipelines.RedisPipeline:400,}# 下载中间件反爬配置 DOWNLOADER_MIDDLEWARES{# 随机User-Agent避免被识别scrapy.downloadermiddlewares.useragent.UserAgentMiddleware:None,scrapy_fake_useragent.middleware.RandomUserAgentMiddleware:400,# 随机代理IP分布式必配避免单IP被封新手可先注释# douban_books_distributed.middlewares.ProxyMiddleware: 500,}# 随机User-Agent配置FAKEUSERAGENT_PROVIDERS[scrapy_fake_useragent.providers.FakeUserAgentProvider,scrapy_fake_useragent.providers.FakerProvider,]2. 修改爬虫文件douban_books.py替换spiders/douban_books.py内容核心是继承RedisSpider而非默认的Spiderimportscrapyfromscrapy_redis.spidersimportRedisSpider# 分布式爬虫核心类fromdouban_books_distributed.itemsimportDoubanBooksDistributedItemclassDoubanBooksSpider(RedisSpider): 分布式爬虫继承RedisSpider从Redis获取start_urls namedouban_booksallowed_domains[book.douban.com]# 单机爬虫start_urls [https://book.douban.com/top250]# 分布式爬虫从Redis的REDIS_START_URLS_KEY获取start_urlsredis_keydouban_books:start_urls# 必须和settings中的一致defparse(self,response): 解析TOP250列表页提取书籍详情页URL # 提取当前页的书籍详情页链接book_linksresponse.xpath(//div[classpl2]/a/href).extract()forlinkinbook_links:yieldscrapy.Request(link,callbackself.parse_book_detail)# 提取下一页链接next_pageresponse.xpath(//span[classnext]/a/href).extract_first()ifnext_page:next_urlresponse.urljoin(next_page)yieldscrapy.Request(next_url,callbackself.parse)defparse_book_detail(self,response): 解析书籍详情页提取核心数据 itemDoubanBooksDistributedItem()# 书籍标题item[title]response.xpath(//h1/span/text()).extract_first().strip()# 书籍评分item[score]response.xpath(//strong[classll rating_num]/text()).extract_first().strip()# 书籍作者item[author]response.xpath(//div[idinfo]/span[1]/a/text()).extract_first()or# 书籍简介item[intro]response.xpath(//div[classintro]/p/text()).extract_first()or# 书籍URLitem[url]response.urlyielditem3. 定义Itemitems.pyimportscrapyclassDoubanBooksDistributedItem(scrapy.Item):# 书籍标题titlescrapy.Field()# 书籍评分scorescrapy.Field()# 书籍作者authorscrapy.Field()# 书籍简介introscrapy.Field()# 书籍URLurlscrapy.Field()4. 可选自定义Pipelinepipelines.py将数据保存到本地Excel/MySQL分布式建议统一存储importpandasaspdfromdatetimeimportdatetimeimportosclassDoubanBooksDistributedPipeline:def__init__(self):self.items[]# 临时存储Itemdefprocess_item(self,item,spider):self.items.append(dict(item))returnitemdefclose_spider(self,spider): 爬虫结束时将数据保存到Excel # 创建保存文件夹ifnotos.path.exists(douban_books_data):os.makedirs(douban_books_data)# 生成Excel文件名filenamefdouban_books_data/豆瓣书籍TOP250_{datetime.now().strftime(%Y%m%d_%H%M%S)}.xlsx# 保存到Exceldfpd.DataFrame(self.items)df.to_excel(filename,indexFalse,engineopenpyxl)spider.logger.info(f数据已保存到{filename}共{len(self.items)}条)步骤3启动分布式爬虫集群1. 向Redis添加初始URLMaster服务器# 连接Redisredis-cli -h 你的RedisIP -p6379-a 你的Redis密码# 向redis_key添加初始URL和settings中的REDIS_START_URLS_KEY一致LPUSH douban_books:start_urls https://book.douban.com/top2502. 启动多个Slave爬虫所有服务器在每台Slave服务器上执行cddouban_books_distributed scrapy crawl douban_books✅ 效果所有Slave自动从Redis获取URL任务爬取的URL会自动加入Redis队列供其他Slave继续爬取已爬取的URL会存入Redis去重集合避免重复爬取爬虫中断后重启会从Redis继续未完成的任务。四、Redis队列监控关键查看分布式状态启动爬虫后通过Redis命令监控任务队列和去重状态# 1. 查看待爬取的URL队列长度越多表示任务越多LLEN douban_books:start_urls# 2. 查看已爬取的URL去重集合数量越多表示已完成越多SCARD douban_books:dupefilter# 3. 查看存入Redis的Item数量如果启用了RedisPipelineLLEN douban_books:items# 4. 查看Redis所有键确认队列和去重集合存在KEYS *五、新手常见问题解答避坑指南1. 爬虫启动后无反应Redis队列长度为0原因初始URL未添加到Redis或redis_key配置不一致。解决方法重新执行LPUSH douban_books:start_urls https://book.douban.com/top250检查settings.py中的REDIS_START_URLS_KEY和爬虫的redis_key是否一致。2. 多台Slave爬取重复数据原因去重机制未生效或Redis连接失败。解决方法检查DUPEFILTER_CLASS scrapy_redis.dupefilter.RFPDupeFilter是否配置用redis-cli连接Redis执行SCARD douban_books:dupefilter确认数量在增长检查Redis密码、IP、端口是否正确。3. 爬虫报错“Connection refused”原因Redis服务器未开放6379端口或防火墙拦截。解决方法在Redis服务器执行ufw allow 6379开放端口检查Docker容器是否映射6379端口docker ps查看端口映射用ping 你的RedisIP测试网络连通性。4. 爬取速度慢并发上不去原因并发配置过低或下载延迟过大。解决方法调整CONCURRENT_REQUESTS建议16-32、CONCURRENT_REQUESTS_PER_DOMAIN建议8-16适当降低DOWNLOAD_DELAY但不要低于0.5避免被封新增Slave服务器直接提升并发量。5. 被封IP爬虫频繁报错403原因分布式爬虫共用IP易被识别。解决方法添加代理IP池中间件ProxyMiddleware每台Slave使用不同的代理IP进一步降低并发量增加DOWNLOAD_DELAY启用RetryMiddleware自动重试失败请求。六、进阶优化提升分布式爬虫稳定性1. 代理IP池集成必配# middlewares.py 新增代理中间件importrandomclassProxyMiddleware:def__init__(self):# 代理IP池替换成你的有效代理self.proxies[http://123.45.67.89:8080,http://98.76.54.32:8888,]defprocess_request(self,request,spider):proxyrandom.choice(self.proxies)request.meta[proxy]proxy spider.logger.info(f使用代理IP{proxy})2. 任务优先级队列将重要URL比如详情页设置高优先级优先爬取# settings.py 配置优先级队列SCHEDULER_QUEUE_CLASSscrapy_redis.queue.PriorityQueue# 爬虫中设置优先级数字越大优先级越高yieldscrapy.Request(link,callbackself.parse_book_detail,priority10)3. 数据分片存储多台Slave将数据写入不同文件最后合并# pipelines.py 按服务器IP分片importsocket hostnamesocket.gethostname()ipsocket.gethostbyname(hostname)filenamefdouban_books_data/豆瓣书籍_TOP250_{ip}_{datetime.now().strftime(%Y%m%d_%H%M%S)}.xlsx总结核心知识点回顾分布式爬虫核心用Redis替代Scrapy本地队列和去重实现多机协同关键配置SCHEDULERRedis调度器、DUPEFILTER_CLASSRedis去重、redis_key任务队列Key是分布式改造的3个核心运维关键通过Redis命令监控队列长度和去重数量及时发现问题反爬重点控制并发量、添加代理IP池、设置下载延迟避免被封IP。实战关键点先搭建Redis环境确保所有Slave能连通Master从简单的低反爬网站如豆瓣TOP250入手熟悉分布式流程优先保证数据不重复、爬虫稳定再提升爬取速度。这个分布式架构不仅适用于豆瓣书籍还能扩展到电商、新闻、社交平台等场景掌握后可轻松处理千万级数据采集任务如果实践中遇到问题欢迎随时交流