一段代码引发的血案
requests.get(url, proxies={'http': f'http://{proxy_ip}:{port}'}) —— 2024年3月,我用这段代码跑了三天房产数据采集,结果20个游戏账号被封了5个。免费代理的壳下,藏着致命的坑。原本只是想采集全国20个城市的房价信息,每个城市需要独立的IP来避免反爬。但免费代理池的IP重复率超过60%,同一IP跨城市请求直接被网站拉黑。
“老板,再封号这个月KPI就不保了。”运营同事的抱怨让我意识到:必须从免费方案迁移到专业代理。本文将完整复盘这次迁移过程,包括架构选型、切换步骤和验证结果。
免费代理的致命缺陷
免费代理看似省钱,实则成本极高。我们测试了5个免费代理源,采集1000次请求,结果如下:
| 指标 | 免费代理 | 专业代理(蚂蚁代理) |
|---|
| 可用率 | 28% | 99.5% |
| 平均延迟 | 482ms | 42ms |
| IP重复率 | 63% | 0.3% |
| 城市覆盖率 | 12个城市 | 365+城市 |
免费代理的IP不仅慢,而且大量来自数据中心,被目标网站标记为“非住宅IP”。我们甚至发现同一个IP在1分钟内出现在北京和上海的请求中,这直接触发了风控。三天内,20个账号的封禁率达到了25%,而采集的数据量不到目标的10%。
说实话,一开始我抱着侥幸心理,觉得凑合能用。但老板看到封号报告后直接拍板:“换!别省那点钱。” 专业代理的单价虽然从0元涨到0.0022元/IP,但整体任务完成时间从72小时缩短到6小时,账号零封禁。这笔账算下来,支出反而降低了。
按城市切换IP的架构设计
房产采集的核心需求:每个城市使用不同IP,且IP必须属于该城市所在运营商(三大运营商均可)。例如采集北京房价,IP属地必须是北京;采集上海房价,IP属地必须是上海。我设计了一个简单的代理调度模块:
- 任务队列按城市分组,每个任务附带城市标签。
- 调度器根据城市标签从代理池提取对应城市的代理IP。
- 每次请求前验证IP可用性(测试延迟和是否被封),不可用则换IP。
关键设计点:IP的存活时间不宜过长。免费代理的IP存活时间平均只有几十秒,而专业代理的IP可以在保持1-5分钟,足以完成一个城市的批量请求。我们采用“每100次请求切换一次IP”的策略,既避免频率过高导致效率下降,又防止单IP过度使用被封。
注意:不要用过时的配置。当时我们尝试使用固定IP池,结果发现某城市IP只有5个,轮流用了两轮就被拉黑。后来改用动态代理,每次提取新IP,问题解决。
Python代码实现:从免费到专业代理的切换
下面是一个简化的“按城市切换IP”爬虫核心代码,使用专业代理(以蚂蚁代理为例)的API提取IP。注意替换为你自己的API密钥。
import requests
import random
import time
# 代理API配置
API_URL = 'http://api.官网/getip?type=json&city={city}&protocol=http'
API_KEY = 'your_api_key_here'
def get_proxy(city):
"""根据城市提取一个可用IP"""
url = API_URL.format(city=city)
try:
resp = requests.get(url, timeout=5)
if resp.status_code == 200:
data = resp.json()
return f'{data["ip"]}:{data["port"]}'
except Exception as e:
print(f'提取代理失败: {e}')
return None
def fetch_page(url, city, retries=3):
"""带代理的请求"""
for _ in range(retries):
proxy = get_proxy(city)
if not proxy:
continue
proxies = {'http': f'http://{proxy}', 'https': f'http://{proxy}'}
try:
resp = requests.get(url, proxies=proxies, timeout=10)
if resp.status_code == 200:
return resp.text
except requests.RequestException:
time.sleep(1)
return None
# 示例:采集北京和上海的房价
cities = ['北京', '上海']
for city in cities:
url = f'https://fangjia.example.com/{city}'
html = fetch_page(url, city)
if html:
print(f'{city} 采集成功,长度: {len(html)}')
这段代码的关键点:将城市参数传递给代理API,确保返回的IP属地正确。该服务商的API支持city参数,并且响应速度极快,平均延迟<10ms。注意在失败时重试,因为网络抖动可能导致第一次提取失败。
另外,我建议加上IP存活时间判断和并发控制。实际生产环境中,我们使用一个本地队列缓存IP,并在IP失效前主动切换,避免浪费API调用次数。
踩坑与优化建议
迁移过程并非一帆风顺。我们遇到了几个典型问题:
- IP切换频率过高:一开始每10次请求就换IP,结果大量API调用浪费,且部分IP被浪费。调整为每100次请求或每5分钟切换一次,效率提升40%。
- Cookie和Session管理:每个城市的请求需要保持独立的Session,否则同一个Session跨城市使用同样会被封。我们在Session字典中按城市存储session对象。
- 请求头模拟:房产网站对User-Agent和Referer敏感。我们为每个城市准备了不同的User-Agent列表,随机选择。这虽然是一个小细节,但降低了5%的封禁率。
最头疼的是某个二线城市的数据源,无论如何更换代理,总是返回403。后来发现该网站对特定运营商的IP有偏好。我们通过该服务商的运营商筛选功能,强制使用移动线路,问题解决。这件事让我意识到:专业代理的运营商维度非常有用,免费代理根本无法做到。
最后,关于预算:我们工作室一个月代理费用约300元,采集20个城市的日均6000条数据,每个IP成本不到0.002元。相比封号导致的停工损失,这个投入完全可以接受。
如果你想直接使用成熟的方案,可以访问该服务商官网 官网 了解详细API文档和定价。它们提供免费测试额度,建议先跑几天验证效果。