先纠正一个流传很广的错误:被封不是因为请求头
做竞品监控的同行里有个说法:只要把 UA、Referer、Accept-Language 拼得跟真浏览器一模一样,免费代理池随手抓一堆就能跑。我信了整整四个月。翻封禁日志的时候才发现,92% 的命中点根本不在请求头,而在 IP 的“出身”上——同一个 C 段在 24 小时内出现在十几个不同目标站点的访问记录里,风控模型压根不用看 UA 就知道你不是人。
我们这套系统盯 380 个竞品站点的价格页和库存页,日请求量在 110 万到 130 万之间浮动,全部走定时任务,采完还要做 diff 比对。免费池跑第一个月,日均可用率 38%,单次任务失败重试率 41%。最折磨人的不是失败本身,是失败得毫无规律:昨天跑得好好的 60 多个域名今天集体挂掉,排查两小时,结论是池子里那批 IP 被整段拉黑了,而我的调度器还在往里派任务。
后面这段是迁移过程。踩的坑比选型结论更值钱。
迁移前先算清账:免费池的贵不在明面上
我最初的算法是错的。免费代理成本为 0,商业代理一天几十块,账面看是纯支出。后来把两个月的故障工时摊进去,结论整个反过来了。
| 方案 | 实测可用率 | 脏 IP 率 | 单域名连续可用时长(中位数) | 月故障工时 |
|---|
| 免费公开池 | 38.2% | 57% | 2.1 天 | 21 小时 |
| 某按量平台(0.008 元/IP) | 76.5% | 22% | 4.3 天 | 7 小时 |
| 专业隧道代理(16 元/天档) | 99.9% | <3% | >14 天 | <1 小时 |
这里的脏 IP 率指的是:抽样 500 个 IP,其中在近 30 天内被我们目标站点封禁过的比例。这个指标比“池子多大”诚实得多,因为大部分平台宣传的 IP 总量里,有相当一部分是别人已经用废的。按一个爬虫工程师的故障排查工时报价折算,21 小时够买三个月隧道了。这笔账我算晚了两个月,说实话挺亏。
选型:池子大小是最没用的那个指标
横向比了 5 家之后,我发现一个反直觉的结论:宣称 3000 万 IP 池的和宣称 500 万 IP 池的,在我们这个场景下实际可用率只差 6 个百分点,池子规模差了 6 倍。竞品监控是固定目标、长周期、低频次的采集,真正决定成败的是“对同一批域名持续给出干净 IP 的调度能力”,不是总量。选 SEO 代理 IP 时把池子大小当第一指标,方向从一开始就偏了。
我最后收窄到三个硬指标:一是城市级切换能力,竞品有区域定价页面,必须按城市维度取数;二是隧道会话保持时长,能撑过 10 分钟的会话比每请求轮换更适合我们的 diff 逻辑;三是白名单接入,长期任务不适合反复走账密认证。综合性价比这块,蚂蚁代理的隧道档在我们这里跑得最稳,延迟中位数 8ms 出头,365+ 城市的覆盖也够用。
切换:灰度 + 白名单,别一次性搬流量
第一次迁移我图快,直接把 380 个域名全切过去,结果第二天目标站风控升级,全线掉到 60% 可用率,连回滚都没法快速验证。第二次老老实实做灰度:
- 按流量分三批,先切 10%(38 个域名),观察 48 小时;
- 每天固定 3 个时间点抽 200 个请求做人工核验,确认返回的是真实页面而不是验证码页;
- 每批切换前把旧通道保留至少 72 小时,用于对比同一时间点的数据一致性;
- 并发从 20 起步,每 12 小时加 5,记录可用率曲线。
配置上,我用的是白名单 + 会话保持的组合。隧道地址固定,靠请求头里的会话标识区分任务,比每请求提取新 IP 稳定得多:
import requests
SESS = requests.Session()
SESS.proxies = {
"http": "http://tunnel.xxx:8080",
"https": "http://tunnel.xxx:8080",
}
# 同一竞品域名复用同一会话,避免 diff 逻辑错乱
SESS.headers.update({
"Proxy-Session": hashlib.md5(domain.encode()).hexdigest()[:12],
"User-Agent": random.choice(UA_POOL),
})
R = SESS.get(url, timeout=(3, 10))
超时配置我改过一次:一开始用 (5, 15),失败重试堆了一堆;改成(3, 10) + 熔断阈值 5 次/分钟之后,坏 IP 的连锁反应基本消失了。
验证:14 天数据和一个意外拐点
灰度跑满两周,数据比我预期的好,但也有个没想到的地方。
| 指标 | 迁移前 | 迁移后 | 变化 |
|---|
| 任务成功率 | 52.8% | 99.3% | +46.5pt |
| 平均单请求耗时 | 1.4 s | 0.6 s | -57% |
| 因封禁导致的重复采集 | 37 万次/月 | 1.1 万次/月 | -97% |
| 人工介入次数 | 18 次/月 | 1 次/月 | — |
意外的是并发拐点。并发推到 60 之后,可用率反而从 99.3% 掉到 94.1%。我一开始以为是代理侧限流,抓包看了才发现是目标站按 IP 维度的滑动窗口限流——轮换太密,每个 IP 都停留在“半热”状态,既没积累到正常访问画像,又刚好踩在阈值边缘。把并发压回 45,稳定在 99% 以上。这个结论跟“并发越高吞吐越大”的直觉是反的,但在长周期监控场景里很常见。
现在这套跑了五个多月,中间只出过一次两小时的抖动,原因是目标站做了一次短时灰度发布。对每天跑百万级请求的监控系统来说,这套方案的稳定性已经完全够用;如果你要做的是秒级高频轮询,那压力模型和安全边界还得另算。完整的接入方式和参数说明在 mayihttp.com 上都能查到,配置项和我上面写的对得上。