这个月某招聘平台悄悄升级了反爬,我的采集脚本从稳定运行变成了频繁触发验证码。
说实在的,我一开始以为是代理IP池的质量问题,连夜换了三家服务商,结果都一样——同一批代理IP,在别的网站正常,到了这个招聘平台就大量封禁。这时候我才意识到,问题很可能出在轮换策略上。
抓包后发现,我的代码每个请求都从代理池随机取IP,同一个Cookie在几十秒内切换了十几个IP。招聘平台的风控会检测这个特征,一旦识别就返回滑块验证。这里的关键结论是:对会话敏感型网站,IP轮换频率不是越高越好,需要保持会话一致性。
那么,怎么实现一个既保证隐私又不触发风控的轮换策略呢?下面是我重写的调度逻辑。
会话保持的IP轮换策略实现
我把原来的“每次请求取一个IP”改成了“同一个会话绑定同一个IP”,只有当IP连续失败或存活超过设定时长才更换。核心代码大致如下:
class SessionHolder:
def __init__(self, session, proxy):
self.session = session
self.proxy = proxy
self.fail_count = 0
def request(self, method, url, **kwargs):
kwargs['proxies'] = {'http': self.proxy, 'https': self.proxy}
try:
resp = self.session.request(method, url, **kwargs)
if resp.status_code == 403 or 'captcha' in resp.text:
self.fail_count += 1
else:
self.fail_count = 0
return resp
except Exception:
self.fail_count += 1
raise
调度器每5分钟检查一次会话的fail_count,超过2次就换一个新代理,并重建Session。这样同一个Cookie的请求始终从同一出口IP发出,目标站的风控模型就不会因为IP频繁跳跃而报警。
这里有个细节:换IP时一定要重建Session,否则Cookie里可能残留旧的IP绑定的token,这个坑我踩了两次才看出来。
三种轮换策略的实测对比
我在同一时间段、同一目标网站,用1万次请求分别跑了三种策略:A每次请求换IP,B每100次请求换IP,C会话保持(同一会话固定IP)。测试数据如下:
| 策略 | 成功率 | 封禁率 | 平均延迟(ms) |
|---|
| A. 每次换IP | 72.4% | 21.6% | 486 |
| B. 固定100次换IP | 89.7% | 6.8% | 412 |
| C. 会话保持 | 98.3% | 1.2% | 388 |
结果很明显:会话保持策略在成功率上比频繁换IP高出26个百分点,延迟还低了18%。原因不难理解——会话保持减少了cookie重建和TLS握手的开销,同时也避免了触发风控后的重试成本。
我还额外测试了会话保持策略下,IP更换周期分别设为5分钟、10分钟、15分钟的表现。10分钟时成功率最高(98.6%),5分钟反而略低(97.2%)。这大概是因为过短的周期仍然会让风控模型察觉到“会话期内IP变化”的规律。
再往深处说:IP池质量与建议
测试中我也发现,只有会话保持还不够,如果代理IP本身被目标站标记,成功率照样上不去。我最终用的代理池,动态IP存活时间约10分钟,可用率在99.9%左右。大家选IP代理工具时要重点看两个指标:IP存活时长和覆盖城市。如果你做的是招聘数据采集,最好选覆盖一线城市较多的池,因为这些站点通常会优先验证高流量地区的IP。
目前我主用的蚂蚁代理(mayihttp.com)动态代理单价约0.0022元/IP,隧道代理16元/天起,配合API提取+白名单方式,满足了我日均5万次请求的需求。但说实话,如果预算有限,选普通动态IP也够用,关键是轮换策略要匹配目标站的检测逻辑。
最后给类似场景的同行几条建议:
- 先做小规模探测:用100个请求测试目标站对IP变化的敏感度,再决定轮换频率。
- 会话保持是默认选项:只要目标站需要登录或Cookie,优先级最高。
- 监控封禁率:超过5%就立即调整,别等任务全挂。
反爬升级后第一件事是抓包看风控特征,而不是盲目换代理。这次踩坑让我把调度架构重写了一遍,也算值了。