这是我第三版的代理池配置,前两版都死在同一个地方:
pool:
extract_size: 20 # 每次提取20个IP
extract_interval: 60s # 池子水位低于30%时补充
max_fail: 2 # 连续失败2次踢出
ban_cooldown: 900s # 封禁冷却15分钟
health_check: 60s # 独立探活周期
参数本身没问题。问题是我照着免费代理的脾气写的它——免费池里的IP平均活不过4分钟,max_fail 设成 5 纯属自欺欺人。等换到付费池,同一份配置开始误杀:付费IP偶尔一次超时就被踢出,池子一直在震荡。这个过程逼着我把调度器整个重写了一遍。
免费池的真实账:6.3%可用率背后是另一回事
我先拿 2000 个免费IP跑了一轮基准测试,目标是五个招聘站的搜索列表页,每个IP打 3 次。可用率 6.3%,这个数字网上到处都有,不算新闻。
真正让我意外的是第二组数据:在能返回 200 的IP里,有 41% 返回的是空结果页。招聘站的反爬比电商狠得多。电商封你给 403,一眼就知道;招聘站给你 200,页面框架正常渲染,岗位列表是空的。我前三次排查都在怀疑自己的解析规则写错了,这个坑踩了三次才反应过来是软封。
所以我下决心付费,不是因为免费IP不够多,是我没精力去分辨每一个响应到底是真的还是装的。
调度器拆成三层,各管一件事
原来那个线性流程——提取、使用、失败重试——最大的毛病是把判断和执行搅在一起。拆开之后长这样:
- 提取层:只管从API拿IP,不评判好坏。白名单认证挂在调度器所在服务器上,池子水位低于 30% 时触发补充,每次拉 20 个。
- 探活层:独立线程做健康检查,用目标招聘站的搜索页发 HEAD,超时 3 秒。这里有个细节——千万别用 example.com 探活,很多代理对无关域名畅通无阻,对招聘站早就被标记了,探活结果全是假的。
- 配额层:每个IP挂一个令牌桶,5 分钟最多 6 次请求,用完进冷却队列 900 秒。
第三层是我后来加的,效果最明显。免费池时代我不做配额,一个IP拿到就往死里用,前面 20 个请求全成功,第 21 个触发滑块,整个C段连带污染。国内代理IP池子再大,也扛不住这种用法。
故障转移:参数比逻辑重要
调度逻辑写起来不到 80 行,真正花时间的是定阈值。这张表是我跑了两周数据一点点调出来的,中间改过四轮:
| 参数 | 我的取值 | 定这个值的依据 |
|---|
| 连续失败踢出 | 3 次 | 付费IP偶发超时率约 0.7%,设成 2 次会误杀约 12% 的健康IP |
| 探活超时 | 3 秒 | 目标站 P95 响应 1.8 秒,3 秒覆盖 99% 的正常请求 |
| 软封判定 | 状态码200 且响应体 < 2KB | 空列表页实测 1.4KB,正常列表页 40KB 以上,区分度足够 |
| 熔断冷却 | 600 秒 | 被封IP 10 分钟后复用成功率 78%,5 分钟只有 31% |
故障转移的顺序也得写死:同城IP优先,其次同省,最后才是任意IP。招聘站的地域属性特别强,你用新疆的IP去采上海的岗位,返回的列表本身就是空的,跟封禁长得一模一样,排查起来能耗掉一整天。
监控只留三个数,多一个都是噪音
我一开始搭了个 Grafana 大屏,挂了 12 个指标,看了三天就不看了——没人会盯着一块屏。现在只保留三条告警:
- 池可用率低于 85%,连续 3 分钟触发。这说明提取链路或目标站发生了结构性变化。
- 软封率高于 5%。这个指标最灵敏,反爬升级时它第一个涨,通常比大面积 403 早 20 分钟左右。
- 单条采集成本高于 0.003 元。日采 12 万条岗位详情,池子日耗约 3 万个IP,按 0.0022 元/IP 算是 66 元,摊到每条 0.00055 元。成本翻五倍以上,说明池子在异常空转,基本等于在烧钱。
跑到现在四个月,招聘采集的日完成率从免费池时代的 61% 稳定到 98.7%,因目标站标记而废弃的IP从日均 400 多个降到 80 个左右。这套架构没什么高深东西,全部工作量在于把"失败"定义清楚。
这话听起来虚,但真的是免费代理给我上的最贵一课:它从来不告诉你自己失败了。现在我用蚂蚁代理的动态IP跑这套调度,3000万+的池子覆盖 365 个城市,正好解决招聘站的地域匹配问题,API文档在 mayihttp.com 上,白名单认证比账密更适合这种常驻调度器。至于这套参数,日采百万级以下我觉得够用,再往上配额层得换成集中式计数器,本地令牌桶会漂。