公司动态
2026 实测:Scrapy 项目接入代理 IP,哪些坑最容易导致采集不稳定?
带采集团队这些年听得最多的一句话是这家代理不行换一家试试。每次我都让对方先别动把日志发我看看——排查下来大部分所谓的代理质量问题换谁家都会原样复现中间件优先级写错、IP 过了存活期还在用、重试沿用失效 IP、并发超过代理吞吐清一色是配置和机制的错配跟服务商没关系。这篇把我平时排障的完整套路整理出来五类高发原因每条给诊断方法、修复步骤和验证标准按信号对号入座就行不用通读。先对号入座你的不稳定属于哪一类看异常信号直接跳到对应小节。下表按出现概率从高到低排前两条通常能解决大部分问题异常信号高发原因对应小节出口 IP 始终是本机 IP代理像没配一样中间件优先级写错代理从未生效原因一日志出现 407 Proxy Authentication Required鉴权未通过原因二同一 IP 先成功后大量 ConnectionRefused、TCPTimedOutIP 已过存活期原因三日志里 Retrying 多次最终仍失败重试沿用同一个失效 IP原因四大面积 ReadTimeout间歇出现 429并发超过代理额定吞吐原因五多种信号同时出现的按一到五的顺序排别跳着查。排查前三样东西先备齐我接手任何一个采集不稳定的案子第一件事都是确认这三样在不在缺一样后面的步骤就执行不下去DEBUG 级日志。settings.py 里设LOG_LEVEL DEBUG并指定LOG_FILE。只有 DEBUG 级别才会记录每个请求实际使用的 proxy 字段这是后面所有判断的依据。没开 DEBUG 就来问为什么代理不生效的等于蒙着眼排障。curl 最小复现。curl 加-x参数可以脱离 Scrapy 单独测代理连通性把框架配置问题和代理链路问题切开。这是排障里最重要的一刀分不清这两层能在错误的方向上耗一整天。代理后台权限。白名单管理和 IP 提取记录的查看权限排鉴权和存活期问题都要用到。三样备齐后建一个只请求 IP 回显接口的测试 spider作为全程的验证基准返回哪个出口 IP一目了然。原因一中间件优先级写错代理压根没生效这是我见过的头号问题而且最冤——很多人代理配置本身没错只是从来没被应用过。诊断很简单跑一遍测试 spider返回的仍是本机 IP就是它。原理翻一眼 Scrapy 源码就明白内置 HttpProxyMiddleware 的优先级是 750并且它发现请求已设置 proxy 时会直接放行。所以自定义代理中间件必须排在 750 之前写进 meta 的代理才会被应用。社区通行写法是 543:DOWNLOADER_MIDDLEWARES { myproject.middlewares.ProxyMiddleware: 543, }中间件里通过request.meta[proxy]写入接入地址即可。验证标准重跑测试 spider返回 IP 变为代理出口同时 DEBUG 日志的请求行里出现 proxy 字段。两个条件都满足才算修复只满足一个继续查。原因二:407 鉴权失败先切一刀再分头查407 说明请求到了代理服务器但鉴权没过。老规矩先用 curl 切开两层curl -x http://host:port IP回显接口地址curl 同样返回 407问题在鉴权配置本身curl 正常而 Scrapy 报 407问题在框架内的代理写法。白名单方式确认加进白名单的是服务器的出口公网 IP。这里有个坑我每年都要跟人讲好几遍云服务器的出口 IP 和你 SSH 登录用的 IP 经常不是同一个拿错 IP 加白名单是 407 反复出现的头号原因。用 curl 请求任意 IP 回显服务查一下出口 IP别凭感觉填。账密方式凭据直接写进接入地址格式http://user:passhost:port写入meta[proxy]即可不需要额外加请求头。我见过不少人画蛇添足去拼 Proxy-Authorization 头反而把自己绕进去。验证标准:curl 与测试 spider 先后返回 200且连续跑 10 分钟无 407再进正式任务。原因三间歇性连接失败九成是 IP 过了存活期同一个 IP 前几次成功、随后集中爆 ConnectionRefused 或 TCPTimedOut这个模式太典型了基本可以直接锁定存活期问题。诊断动作去代理后台调 IP 提取记录对比失败请求的时间戳和该 IP 的提取时间。时间差超过所选存活档位就是拿失效 IP 在发请求代码再怎么改都没用。修复的关键认知是存活档位要和单批任务耗时对齐剩余寿命撑不完一批页面的 IP 就该提前弃用而不是等它报错。选服务的时候我会优先看档位灵不灵活像极安代理的短效产品把存活期做成 1-15 分钟五档可选到期自动失效、按每日 IP 数计费单页耗时长的任务选长档高频轮换选短档档位选错换档就行不用换产品线。程序侧配合记录每个 IP 的提取时间戳请求前先算剩余寿命把用到死改成提前退休。验证标准修复后连续跑 1 小时统计 ConnectionRefused 与 TCPTimedOut 占比相比修复前明显回落且不再成批出现即为生效。原因四重试形同虚设默认机制不换 IP这一条最反直觉值得多说两句。很多人看到日志里 Retrying 了好几次还是失败第一反应是重试次数不够加大。错了——Scrapy 内置 RetryMiddleware 默认重试 2 次且重试请求沿用原 meta代理字段原样保留等于拿同一个失效 IP 再试两遍。次数加到 10 次也只是失败得更慢。官方文档写得明白超时、连接拒绝这类异常默认都在重试范围但更换代理要开发者自己实现。诊断方法:DEBUG 日志里找同一 URL 的多行 Retrying 记录对比每行的 proxy 字段地址一模一样即确认。路径一自己重写重试逻辑在重试前更换meta[proxy]class ProxyRetryMiddleware(RetryMiddleware): def process_exception(self, request, spider, exceptionNone, **kw): request.meta[proxy] get_new_proxy() return self._retry(request, exception, spider)路径二把换 IP 交给云端。适合不想维护这段逻辑的团队。我的判断标准是换 IP 代码越写越厚、自建 IP 池的维护本身成了新故障源就该切隧道模式了。隧道代理统一入口接入云端毫秒级自动换 IP、异常 IP 自动切换程序端保留默认重试配置即可每次重试天然走新出口。验证标准路径一用无效代理故意触发重试日志中相邻两行 Retrying 的 proxy 字段应不同路径二观察失败率连接类异常不再随重试累积即为生效。原因五大量超时加 429并发压过了代理吞吐先纠正一个普遍误区并发不是越大越快。超过代理服务的额定吞吐后多出来的请求只会堆进超时队列表现为 ReadTimeout 占比一路走高间歇触发目标站频控返回 429。诊断动作Scrapy 默认CONCURRENT_REQUESTS是 16对照你所用套餐的额定请求数和带宽两个都要看。拿我手上项目的真实配置说我们用的极安隧道基础套餐额定每秒 5 个请求、5M 带宽。带宽这个数顺便展开一下当时选型我对比过几家5M 的起步带宽在国内厂商里算给得大方的不少家基础套餐明显更小同样并发下先撞的往往是带宽墙选型别只盯着 IP 数量和单价。但额定请求数摆在那每秒 5 个的配置下把并发拉到 64 不会更快只会更堵。我见过有团队一边开 64 并发一边投诉代理慢对完额定吞吐才发现是自己把路堵死的。解决三步CONCURRENT_REQUESTS降到与额定吞吐对齐的量级DOWNLOAD_DELAY设 0.5-1 秒并开启随机化启用 AutoThrottle 自动限速框架默认参数是初始延迟 5 秒、最大延迟 60 秒让它在上限内自适应调速。验证标准跑 30 分钟统计超时占比回落到 5% 以内且 429 不再出现即为对齐。仍偏高就继续下调并发注意方向是降并发不是上调超时时间后者只是把问题藏起来。最后哪些情况别硬修老手和新手最大的差别不是会修多少问题而是知道哪些问题不归自己修。三种情况继续调参数纯属浪费时间判断标准就一条问题是否还在代理接入层内。其一关掉代理直连也失败或目标页面改版、接口下线。问题在目标侧或解析层换任何代理都无解。其二数据源需要登录授权或属于非公开数据。这是合规边界不是技术问题。我的立场很明确停止采集回到数据授权路径任何配置手段都不该拿来处理边界问题这条在团队里没有讨论空间。其三白名单确认无误、curl 直测代理仍大面积异常。问题在服务端链路该交给服务商定位。提工单别只甩一句代理不稳定带上这四项信息能最快定位信息项作用异常时间戳对应服务端链路日志区间报错日志片段区分鉴权、连接、超时三类问题接入方式白名单或账密排查路径不同并发量与请求频率判断是否为吞吐配置问题自己修接入层内的问题边界外的交给对的人排查时间才花在刀刃上。总结一下这套排障观采集不稳定先查配置错配再怀疑代理质量顺序别反。五条原因按概率排好了下次系统抖动对着信号表走一遍大概率不用换服务商。评论区欢迎交流尤其想听听大家在原因四上的实现重写重试中间件的有没有遇到过和其他中间件的执行顺序冲突