先纠正一个误区:很多人以为“城市代理IP”就是选了城市,然后IP会自动按城市分配,自己只要调用就行。我在做SEO排名追踪时也这么认为,结果被现实狠狠打脸。原本以为能省心拿数据,谁知免费代理的“城市定向”根本是个伪命题——IP倒是换了不少,可同一IP反复出现,城市定位也经常漂移。
一、免费代理的“城市定向”是个伪命题
我的业务场景是SEO排名追踪:每天要查5000+关键词在12个主要城市的排名,也就是6万次请求。刚开始为了省钱,我用了一个号称“城市IP池”的免费代理。测试了半小时感觉还行,结果跑了一个完整任务后,数据简直没法看:可用率只有62%,重复IP率高达30%,城市定位准确率仅70%。最气人的是,同一个IP在两分钟内被分配给不同城市,导致某个关键词在北京和上海的排名数据一模一样——这显然是错的。
老板当时还说“免费先用着”,结果客户一看数据就投诉了。那次之后我决定换思路:先搞清楚付费城市代理IP的关键指标,再动手写调度。
二、付费城市代理IP的三个关键指标
转向付费代理后,我对比了几家服务商,最终选了蚂蚁代理(mayihttp.com)做主力测试,因为它的城市列表最全,而且支持API提取。这里说三个我踩坑后认为是核心的指标:
- 城市覆盖率:不是所有代理都覆盖全国365+城市,有些只做一二线。实测该服务商的城市覆盖达标,连拉萨、西宁这种边缘城市都有IP。
- IP可用率:付费代理也不是100%可用。该服务商宣称99.9%,我实际测了3天,按小时采样,平均可用率99.6%左右,高峰期略有波动,但比免费代理强太多。
- 轮换粒度:这决定了你能不能让同一个IP在一段时间内只服务一个城市。大多服务商支持“按次/按分钟/按天”轮换,但城市代理IP必须支持按次提取并绑定城市,否则你拿到IP后再指定城市就晚了。
这三项指标直接决定了你的调度能不能跑起来。比如我后来发现,某个服务商虽然城市全,但IP生命周期只有30秒,并发一高队列就空转,反而浪费请求。
三、IP轮换策略设计与代码实现
解决了服务商选择,接下来才是重头戏:怎么设计轮换策略。直接随机取IP在高并发下很容易踩雷——同一秒内两个线程拿到同一个IP,被目标网站识别为异常。我的方案是用Redis维护每个城市的IP队列,每个IP取出后进入冷却池,冷却时间设为60秒,保证同一IP不会在短时间内被重复使用。
下面是核心代码,用Python写的,逻辑很直白(假设已经用代理服务商的API把IP提取并存入Redis的hash结构中):
import redis
import requests
import time
r = redis.Redis(host='localhost', port=6379, db=0)
CITY_KEY = 'city_ip:{city}'
COOL_KEY = 'cool_ip:{city}'
COOL_TTL = 60 # 冷却60秒
def get_city_ip(city):
"""从Redis队列取一个可用IP,优先从冷却池偷一个(仅限紧急情况)"""
# 1. 从主队列弹出一个IP
ip = r.lpop(CITY_KEY.format(city=city))
if ip:
# 立即放入冷却池,并设置过期时间
r.rpush(COOL_KEY.format(city=city), ip)
r.expire(COOL_KEY.format(city=city), COOL_TTL)
return ip.decode()
else:
# 2. 主队列为空,尝试从冷却池偷一个(不推荐,但可以防止任务卡死)
cool_ip = r.lpop(COOL_KEY.format(city=city))
if cool_ip:
return cool_ip.decode()
# 3. 都没有,触发API提取补充
refill_city_ip(city)
return None
def refill_city_ip(city):
"""向服务商API申请新的IP,并写入队列"""
# 这里替换成你的代理服务商API请求
# 该服务商的例子:https://api.官网/ip?city=beijing&num=20
url = f'https://api.官网/ip?city={city}&num=20'
resp = requests.get(url, timeout=5)
ips = resp.json()['data']['ips']
r.rpush(CITY_KEY.format(city=city), *ips)
这个方案的关键是把“取IP”和“回收IP”解耦。之前我犯过傻:每次租一个IP用完就丢,结果IP池消耗极快,成本翻倍。加了冷却池后,一个IP在60秒冷却期内可以被复用一次(对于SEO查询这种低频请求完全够用),成本直降40%。
四、实测效果与成本分析
我用这套方案跑了整整一周,每天6万次请求。对比数据如下:
| 指标 | 免费代理 | 城市代理IP(该服务商) |
|---|
| 可用率 | 62% | 99.6% |
| 重复IP率 | 30% | 2.1% |
| 城市定位准确率 | 70% | 98.7% |
| 平均响应时间 | 1.8s | 0.4s |
| 单次请求成本 | 0 | 0.0022元 |
成本方面:以每次请求消耗1个IP计算,每天6万次,按0.0022元/IP,就是132元。但实际因为冷却复用,日均IP消耗约3.5万个,成本降到77元/天,折合每月约2300元。相比免费代理导致的数据错误带来的客户流失,这点钱简直不值一提。
我特意把任务均匀分散到工作时段,避免同一秒内并发超过50个IP,否则会触发部分网站的滑块验证。这个经验是后来加线程时发现的:一开始并发200,封禁率飙升到15%,降低到50后封禁率降到0.3%。
五、意外发现与经验总结
本来以为完事了,结果顺手跑了一下不同城市的IP池大小,发现一个规律:一二线城市的IP池明显大于三四线。比如北京、上海随便取都有上千个IP,但像拉萨、西宁,同时可提取的IP不到20个。并发任务如果堆到这些城市,队列很容易被掏空。于是我在调度代码里加了“城市权重”:小池子的城市降低并发数,或者提前预取一批IP放到备用队列。
现在这套方案已经稳定运行了两个月,每天5000关键词的排名追踪再没出过差错。如果你只是跑几千次请求,直接随机取IP可能也够用;但像我这种每天数万次、还要限定城市的场景,基于冷却池的轮换策略几乎必备。
最后说句实在话:别迷信大厂的IP池,也别一棍子打死小服务商。先用脚本测几天可用率和城市准确率,再决定买多少量。我这次选该服务商(官网)是因为它的API支持按城市批量提取,而且延迟低、可用率高,但如果你对某些冷门城市有需求,最好提前跟客服确认有没有库存。