一、背景:为什么 AI 训练数据采集需要代理 IP?
AI 模型的训练效果高度依赖数据的规模、多样性 和质量。无论是 LLM 的预训练语料、计算机视觉的图像数据集,还是推荐系统的行为数据,公开网络都是最大的数据源。
然而,目标网站普遍存在以下反爬机制:
| 反爬手段 | 影响 |
|---|---|
| IP 频率限制 | 单 IP 单位时间请求数受限 |
| 地理位置限制 | 部分内容仅特定地区可见 |
| CAPTCHA / 挑战 | 高频请求触发验证码 |
| User-Agent / 指纹检测 | 识别并封禁非浏览器流量 |
| 账号关联检测 | 同 IP 多账号操作被风控 |
稳定、高可用的代理 IP 池,是突破这些限制、实现大规模自动化数据采集的基础设施核心。
二、高并发代理架构设计
2.1 整体架构分层
┌─────────────────────────────────────────┐
│ 采集任务调度层 │
│ (Scrapy / Crawlee / 自研调度框架) │
├─────────────────────────────────────────┤
│ 代理路由网关层 │
│ (负载均衡 + 健康检查 + 协议适配) │
├─────────────────────────────────────────┤
│ IP 池管理中间件 │
│ (获取 / 验证 / 分级 / 调度 / 淘汰) │
├─────────────────────────────────────────┤
│ 代理供应源适配层 │
│ (静态住宅 / 机房 / ISP / 资源代理) │
└─────────────────────────────────────────┘
2.2 IP 池的核心数据模型
@dataclass
class ProxyIP:
host: str
port: int
protocol: str # http / https / socks5
source: str # 供应商标识
ip_type: str # residential / datacenter / isp
# 状态管理
is_alive: bool = True
consecutive_failures: int = 0
total_requests: int = 0
success_rate: float = 1.0
# 速率控制
avg_response_time: float = 0.0
last_used: float = 0.0
cooldown_until: float = 0.0
# 地理属性
country: str = ""
region: str = ""
isp: str = ""
三、关键实现细节
3.1 动态权重调度算法
静态轮询在高并发场景下表现极差。推荐使用基于成功率的动态权重调度:
import asyncio
import time
from heapq import heappush, heappop
class WeightedProxyScheduler:
def __init__(self):
self._proxy_heap = [] # (weight_score, proxy)
self._lock = asyncio.Lock()
def _compute_score(self, proxy: ProxyIP) -> float:
"""综合评分:成功率权重最高,响应时间次之"""
score = 0
# 成功率权重 50%
score += proxy.success_rate * 50
# 响应时间权重 30%(越快越高分)
score += max(0, 1 - proxy.avg_response_time / 10.0) * 30
# 冷却惩罚
if time.time() < proxy.cooldown_until:
score -= 20
# 连续失败惩罚
score -= proxy.consecutive_failures * 10
return max(0, score)
async def acquire(self) -> ProxyIP:
async with self._lock:
while self._proxy_heap:
_, proxy = heappop(self._proxy_heap)
score = self._compute_score(proxy)
if score > 0:
heappush(self._proxy_heap, (score, proxy))
proxy.last_used = time.time()
return proxy
raise RuntimeError("No available proxy")
async def release(self, proxy: ProxyIP, success: bool):
if success:
proxy.success_rate = (
0.9 * proxy.success_rate + 0.1 * 1.0
)
proxy.consecutive_failures = 0
else:
proxy.consecutive_failures += 1
proxy.success_rate *= 0.8
if proxy.consecutive_failures >= 3:
proxy.cooldown_until = time.time() + 60 # 冷却1分钟
proxy.avg_response_time = (
0.7 * proxy.avg_response_time + 0.3 * proxy.avg_response_time
)
3.2 并发连接管理:有限并发 + 自适应节流
import asyncio
import aiohttp
class ThrottledSessionManager:
def __init__(self, max_concurrent: int = 50, proxy_scheduler: WeightedProxyScheduler = None):
self._semaphore = asyncio.Semaphore(max_concurrent)
self._scheduler = proxy_scheduler
self._session: aiohttp.ClientSession = None
async def fetch(self, url: str, **kwargs) -> bytes:
async with self._semaphore:
proxy = await self._scheduler.acquire()
proxy_addr = f"{proxy.protocol}://{proxy.host}:{proxy.port}"
try:
async with self._session.get(
url, proxy=proxy_addr, timeout=aiohttp.ClientTimeout(total=30), **kwargs
) as resp:
data = await resp.read()
await self._scheduler.release(proxy, success=True)
return data
except Exception as e:
await self._scheduler.release(proxy, success=False)
raise
3.3 IP 健康检查探针
实时性是代理池的生命线。需要独立的后台任务持续探测 IP 可用性:
async def health_check_loop(pool: list[ProxyIP], check_url: str, interval: int = 30):
"""后台心跳检查,每30秒轮询一次"""
while True:
for proxy in pool:
try:
async with aiohttp.ClientSession() as sess:
start = time.time()
async with sess.get(
check_url,
proxy=f"{proxy.protocol}://{proxy.host}:{proxy.port}",
timeout=aiohttp.ClientTimeout(total=5)
) as resp:
if resp.status == 200:
proxy.avg_response_time = time.time() - start
proxy.is_alive = True
else:
proxy.is_alive = False
except:
proxy.is_alive = False
await asyncio.sleep(interval)
四、代理源的选择策略
| 类型 | 稳定性 | 并发能力 | 成本 | 适用场景 |
|---|---|---|---|---|
| 静态住宅代理 | ⭐⭐⭐⭐⭐ | 中 | 高 | 对 IP 质量要求极高的场景(如 Google 搜索采集) |
| 机房代理(数据中心) | ⭐⭐⭐⭐ | 极高 | 低 | 大规模通用数据采集 |
| ISP 代理 | ⭐⭐⭐⭐⭐ | 高 | 中高 | 需要真实运营商 IP 的高并发场景 |
| RES(轮转住宅) | ⭐⭐⭐ | 中高 | 中 | 中小规模采集,需要地理分散 |
推荐组合策略 :以机房代理为主力 (70%-80%),保留 20%-30% 的高质量住宅代理用于攻坚(需要高信誉 IP 的场景),配合 ISP 代理应对特定区域需求。
五、实际踩坑经验
- 不要用单线程验证 IP:异步并发验证 100 个 IP 只需 5 秒,而串行需要数分钟
- 设置合理的重试退避:初次失败后等待 1s、二次 5s、三次 30s,避免雪崩
- 区分网络错误和业务错误:TCP 超时 ≠ 被 ban,需要不同处理策略
- 目标网站请求分布策略:同一目标不要集中在少数 IP 上,建议一个 IP 不超过每分钟 10-20 次请求
- 做好 IP 分级:稳定 IP 处理核心任务,新 IP 先发低价值请求"热身"
六、生产级监控
@dataclass
class PoolMetrics:
total_ips: int
alive_ips: int
health_rate: float # alive / total
current_rps: float # 当前每秒请求数
avg_latency: float # 平均延迟 ms
error_rate: float # 最近5分钟错误率
ip_rotation_count: int # 每小时 IP 轮换次数
将以上指标打入 Prometheus + Grafana,设置告警:
- 健康率 < 60% → 报警
- 错误率 > 20% → 报警
- 可用 IP 数低于阈值 → 自动补充
七、总结
构建一个稳定可靠的高并发代理 IP 系统,核心在于三件事:
- 完善的 IP 生命周期管理------获取、验证、分级、调度、淘汰形成闭环
- 智能的动态权重调度------让表现好的 IP 干更多的活,实现整体吞吐最大化
- 实时的健康监控+自动弹性伸缩------问题 IP 秒级摘除,新 IP 秒级补充
这套方案在日采集量 10 亿级、并发数 500+ 的场景下已稳定运行,希望能为正在搭建采集基础设施的团队提供参考。