Python 爬虫代理 IP 在 Scrapy 里怎么做成中间件-易代理
Scrapy 项目为什么不能每个请求手写代理
小脚本用 Requests,大项目用 Scrapy。Scrapy 本身是异步框架,下载器、中间件、管道各管各的。你要是在 Spider 里每个 Request 都手动塞 proxies,代码会又臭又长,还容易漏。
正确做法是在下载器中间件里统一注入。Python 爬虫代理 IP 一旦进 Scrapy 中间件,全项目所有请求都走同一套出口逻辑,后续换池子、加鉴权、做评分都不用改业务代码。
最基础的代理中间件
pythonclass ProxyMiddleware: proxy_url = "http://用户名:密码@网关地址:端口" def process_request(self, request, spider): request.meta["proxy"] = self.proxy_url
settings.py 里启用:
pythonDOWNLOADER_MIDDLEWARES = { "myproject.middlewares.ProxyMiddleware": 350,
}这样 Scrapy 发请求前会自动把 proxy 写进 meta。Python 爬虫代理 IP 的入口只需要维护这一个类,不用散落到各个 Spider。
动态网关和 IP 池的区别
有两种玩法。第一种是动态转发网关,Scrapy 永远连同一个网关地址,服务端每次换出口。这种最省心,代码里没有池子概念。
第二种是自己维护 IP 池,从 API 拉一批地址,放内存里随机取,失败了剔除,定时补。
pythonimport randomclass PoolProxyMiddleware:
proxy_pool = [] def process_request(self, request, spider): if not self.proxy_pool: self.proxy_pool = load_proxy_list_from_api()
proxy = random.choice(self.proxy_pool)
request.meta["proxy"] = f"http://{proxy}"
request.meta["_used_proxy"] = proxyPython 爬虫代理 IP 用池子模式时,必须配套失败回收,不然坏地址越积越多,爬虫不是被目标站封死,是被自己的脏池子拖死。
响应里发现验证页要处理
Scrapy 里不能只看 status。200 也可能返回验证页。可以在 response 中间件里判断关键字:
pythonclass CheckBlockedMiddleware: def process_response(self, request, response, spider): if "请输入验证" in response.text or "access denied" in response.text.lower():
spider.logger.warning(f"触发验证页:{request.url}")
proxy = request.meta.get("_used_proxy") if proxy:
remove_bad_proxy(proxy)
request.meta.pop("proxy", None) return request # 放回调度队列重抓
return response这套逻辑配上 Python 爬虫代理 IP,才能让“被拦”变成可恢复事件,而不是默默存一堆垃圾页进数据库。
并发别无脑拉满
Scrapy 默认 CONCURRENT_REQUESTS 不算小,但代理通道有吞吐上限。你开 32 并发,网关只够 8 路稳跑,剩下全是超时。
更稳的配置思路:
pythonCONCURRENT_REQUESTS = 8DOWNLOAD_DELAY = 1.0RANDOMIZE_DOWNLOAD_DELAY = True
Python 爬虫代理 IP 解决的是身份分散,不解决“你发太快”。节奏控制永远在代理前面。
多蜘蛛不同业务要隔离
如果你一个 Scrapy 项目里跑电商比价、新闻采集、SERP 监控,别用同一个出口池。电商页怕关联,新闻页怕限流,SERP 页怕查询过密,业务性质完全不同。
可以按 spider.name 分配不同网关:
pythonGATEWAY_MAP = { "news_spider": "http://用户:密码@news-gw:端口", "price_spider": "http://用户:密码@price-gw:端口", "serp_spider": "http://用户:密码@serp-gw:端口",
}class BizProxyMiddleware: def process_request(self, request, spider):
request.meta["proxy"] = GATEWAY_MAP.get(spider.name)Python 爬虫代理 IP 做到业务隔离,排障时才不会“一个业务被封,全项目陪葬”。
小结
Scrapy 里接代理,重点不是会写 request.meta["proxy"],而是把出口层做成可观测、可切换、可隔离的中间件系统。Python 爬虫代理 IP 放对位置,爬虫项目才像生产系统,不像玩具脚本。
相关标签:代理ip,ip代理,http代理,代理服务器ip,开放代理,文档中心,新闻,动态住宅ip,ip池,socks5代理