Scarnox · Blog

抓取用轮换代理:配置与常见陷阱

轮换代理会改变你的请求所使用的出口 IP 地址,可以是每个请求换一个,也可以是每隔一段固定时间换一个。它是网页抓取中最常用的工具之一,也是最常被误用的工具之一。轮换得太少,单个地址会被限速;轮换得太频繁,流量又看起来完全不像访客。本指南解释两种轮换模型,给出一个带失效代理重试的可用 Python 方案,并说明代理字段如何配合验证码识别。

轮换与粘性会话

轮换代理服务分配地址的方式有两种:

真实访客在整个访问过程中使用同一个地址。粘性会话模拟的就是这种行为,因此当网站使用 Cookie 或会话时,它通常是更好的默认选择。无状态的爬取则适合按请求轮换。

用 Python 实现一个基础的轮换池

下面的示例维护一个代理 URL 池,依次轮换使用,并在某个代理失败时切换到下一个。凭据请保存在环境变量中,绝不要写进源代码。

import itertools
import os
import requests

# 代理 URL 从环境变量读取,例如:
# PROXY_POOL="http://user:pass@203.0.113.10:8080,http://user:pass@203.0.113.11:8080"
PROXIES = [p.strip() for p in os.environ.get("PROXY_POOL", "").split(",") if p.strip()]
rotation = itertools.cycle(PROXIES)

def fetch(url: str, max_tries: int = 3) -> requests.Response:
    last_error = None
    for _ in range(max_tries):
        proxy = next(rotation)
        try:
            r = requests.get(
                url,
                proxies={"http": proxy, "https": proxy},
                timeout=30,
            )
            if r.status_code == 407:  # 代理认证失败
                raise requests.RequestException("proxy auth rejected")
            return r
        except requests.RequestException as exc:
            last_error = exc  # 代理失效或过慢:换下一个
    raise RuntimeError(f"all attempts failed for {url}: {last_error}")

这里有两个细节很关键。第一,失效的代理应当换一个不同的地址重试,而不是继续用同一个。第二,遇到认证错误的请求应当停止并上报,而不是把整个池子都耗尽。

追踪代理健康状况

简单的轮询会持续把流量发送给已经开始失败的代理。请为每个地址记录一个简单的分数:统计近期失败次数,一旦超过阈值,就把该地址从池中移出一段冷却期。之后再把它放回,并继续观察。这样,你的抓取器就会把请求花在池中健康的那部分上。

每个结果都要记录所用的代理。当网站开始返回封锁页面时,你会想知道是某一个地址、某一个地区,还是整个池子造成的。

控制池子的节奏

轮换会把负载分散到多个地址上,但每个地址仍然有自己的速率。请为每个地址设置延迟,并为整个池子设置每秒请求数的全局上限。轮换并不是发送更多流量的许可,它只是让每个地址的流量保持在合理范围内的一种方式。

常见错误

大多数轮换问题都源于少数几种习惯。在登录或结账流程中途更换地址,会打断会话,并让网站产生怀疑。429 响应表示的是网站对你的限速,而不是代理出了问题,因此立即换一个地址再重试,只会让问题扩散。在保留同一批 Cookie 的同时每次请求都更换地址,也同样不一致,因为这些 Cookie 是发给另一位访客的。最后,一个从不检查的池子会悄悄积累大量失效的地址,你的错误率会在没有明显原因的情况下上升。请定期检查池子,并移除失败的地址。

代理与验证码识别

有些验证码任务可以使用你的抓取器所用的代理。你可以通过可选的 proxy 字段传入它,格式为 http://user:pass@host:port,识别就会从你的页面请求所走的同一网络路径发出。无代理任务则完全跳过这个字段。选择哪一种,取决于网站是否把验证码绑定到网络地址,这种权衡在代理与无代理验证码识别中有详细说明。

两个实际要点:

Scarnox 目前上线的验证码类型是 PopularCaptcha。PopularCaptcha Python 指南展示了请求的方式,以及如何提交返回的 token。

如何选择代理

你轮换的地址类型,与轮换机制本身同样重要。数据中心地址速度快、单次请求成本低,但往往得分较低。住宅地址得分较好,但速度较慢。住宅代理与数据中心代理对比一文对两者做了深入比较,其中的建议同样适用于你在这里构建的代理池。

负责任地抓取

下一步

免费试用额度,无需信用卡:注册账户,并使用你自己的代理试用 PopularCaptcha 流程。当前费率请查看定价页面。