上个月团队开会,讨论要不要把房价采集的城市从40个铺到300个。运营那边的需求很直接:竞品分析要按城市出报表,缺一个城市就缺一块结论。我当时凭经验判断,用现有的动态短效代理加个城市参数就能搞定,先跑一周再说。结果三天后数据组同事把报表甩到我桌上——成都的均价跑出了西安的数字,深圳的楼盘跳到了东莞。
那次翻车让我重新把网页代理IP这件事从头拆了一遍。下面是我完整的选型、部署和验证过程。
需求拆解:问题不在能不能访问,而在“像不像当地人”
先说清楚量级。300个城市,每城抽3个区县,每区县25个在售楼盘,每个楼盘抓详情页、价格走势页和历史成交页,合计约6万个页面/天,高峰期并发40。这个量不算大,但房产站点的反爬逻辑很刁钻。
我把踩到的拦截分成三类:
- 地域校验:请求IP的归属地与URL里的城市参数不一致,直接返回403或一个空白的价格区块,不带任何报错提示——这也是最坑的,程序以为成功了。
- 会话频控:同一个IP在一小时内访问同一城市的楼盘页超过60次,开始弹滑块。
- 行为指纹:连续请求间隔恒定在200ms以内,触发风控打标,后续所有请求降级到验证码通道。
所以真正的选型指标是三条:城市级定向能力、会话粘性时长、失败后的快速替换成本。延迟排在第四位,因为6万页面的量级,只要单请求在1秒内,一天跑得完。
三档方案实测:免费代理、短效动态、城市定向隧道
我们横向跑了一周,每档方案各跑5000个页面,人工抽检价格字段的正确性。这里有个意外的发现:本来只是想测延迟,顺手统计了城市命中率,才发现问题最大的是免费代理这一档。
| 方案档位 | 可用率 | 平均响应 | 城市命中率 | 封禁率 | 折算单页成本 |
|---|
| 免费公开代理 | 31.2% | 2140ms | 12% | 41.6% | ≈0元(但返工占掉两个人日) |
| 短效动态IP(机房) | 96.3% | 320ms | 87.5% | 6.7% | 0.0041元 |
| 城市定向隧道代理 | 99.9% | <10ms(接入层) | 99.2% | 1.4% | 0.0022元/IP |
短效动态这一档的问题不是质量差,而是城市池不均衡:一线城市货源充足,三四线城市经常提取到相邻城市的IP,命中率掉到70%以下。我一开始以为按天计费的隧道更省事也更便宜,跑完账才发现要看你单IP跑多少个页面——隧道按天包月适合高频复用,短效按量更适合我们这种“每城打一枪就走”的模式。最终我们用的是混合:一线城市走隧道,其余城市走按量提取的短效。
接入方式上,我选的是API提取加白名单双通道。白名单省掉了每次请求带账密的握手开销,API提取则用来做城市级精确调度。蚂蚁代理在这套组合里是我们目前的主力供应商,3000万+IP池覆盖365+城市,按城市参数提取时基本能做到要哪个区给哪个区。
部署配置:按城市提取 + 指数退避 + 城市级熔断
核心代码不长,重点是重试策略要按城市维度做,不能全局一刀切。
- 按城市编码从API提取IP,单次提取量按并发数×2准备余量;
- 同一城市内的多个请求复用同一IP,保证会话粘性,避免价格区块因切换IP而返回缓存脏数据;
- 单城市连续失败达10次,熔断5分钟并告警,防止一个城市的反爬升级拖垮整条流水线。
import requests, time
CITY = {"北京": "110000", "成都": "510100"}
def fetch(url, city, retry=3):
for i in range(retry):
proxy = get_proxy(CITY[city]) # 按城市提取
try:
r = requests.get(url,
proxies={"http": proxy, "https": proxy},
timeout=8, headers={"User-Agent": UA})
if r.status_code == 200 and "验证" not in r.text:
return r.text
except Exception:
pass
time.sleep(1.2 ** i) # 指数退避,别硬刚
circuit_break(city) # 触发城市级熔断
return None
这里有个隐藏配置值得说:提取接口返回的IP要带归属地字段,我们用它做二次校验,归属地不匹配的IP直接丢弃而不是重试。这一个判断把脏数据率从9%压到了0.3%,比换供应商管用。
验证结果与适用边界
调整后连跑两周:封禁率从27%降到1.4%,价格字段抽检准确率99.6%,6万页面/天的任务在4.5小时内跑完,比原来缩短了近一半。回头看,真正解决问题的不是换了更贵的代理,而是把“城市”当成了调度的一等公民。
说句实话,这套方案在我们这个量级够用。如果你每天只跑几千个页面,或者城市固定在十个以内,上熔断和城市级调度就有点重了,几台拨号机加简单轮换反而更省心。另外提醒一句,隧道代理的<10ms是接入层延迟,不等于端到端响应,测性能的时候别被这个数字误导。完整的提取参数和城市编码表可以在 mayihttp.com 的文档里对着改。