Explainers

轮换自有服务器基础设施:验证码解决的最佳实践

轮换自有服务器基础设施为每个请求(或每个会话)分配一个新的真实用户 IP。对于验证码密集型工作流程,正确的轮换策略可以将挑战率降低 50-80%,而 CaptchaAI 会处理其余的事情。


为什么住宅 IP 减少验证码

代理类型 知识产权来源 验证码率 为什么
数据中心 云/hosting提供商 高 (30-70%) 已标记的已知 IP 范围
住宅 真正的家庭 ISP 低(5-15%) 看起来像真实用户
移动的 蜂窝运营商 非常低(1-5%) 被数千名用户分享
互联网服务供应商 静态住宅级 低(5-10%) 结合速度+信任

CAPTCHA 系统(尤其是 reCAPTCHA)检查 IP 信誉数据库。来自真实 ISP 的住宅 IP 具有干净的历史记录,因为它们属于真实的订户。


轮换策略

1. 按请求轮换(默认)

import requests

proxies = {
    "http": "http://user:pass@gateway.proxy.com:7777",
    "https": "http://user:pass@gateway.proxy.com:7777",
}

# Each request gets a new IP
for url in urls:
    resp = requests.get(url, proxies=proxies, timeout=30)
    # New IP after each request

最适合: 跨不同站点抓取许多页面。 验证码风险: 每个请求较低,但无法维持会话。

2. 粘性会话轮换

import random
import string

def get_sticky_session(duration_min=10):
    session_id = "".join(random.choices(string.ascii_lowercase, k=8))
    return {
        "http": f"http://user-session-{session_id}:pass@gateway.proxy.com:7777",
        "https": f"http://user-session-{session_id}:pass@gateway.proxy.com:7777",
    }

# Same IP for the whole CAPTCHA workflow
session_proxy = get_sticky_session(duration_min=10)

# Step 1: Load page
resp = requests.get("https://staging.example.com/qa-form", proxies=session_proxy)

# Step 2: Solve CAPTCHA (same IP)
token = solve_captcha("https://staging.example.com/qa-form", sitekey)

# Step 3: Submit (same IP — required for token validity)
resp = requests.post("https://target.com/submit", proxies=session_proxy, data={
    "g-recaptcha-response": token,
})

最适合: 验证码保护的表单和多步骤工作流程。 验证码风险:非常低——一致的 IP 可以建立信任。

3. 按域轮换

domain_sessions = {}

def get_domain_proxy(domain):
    """Same IP per domain, different IP per domain."""
    if domain not in domain_sessions:
        session_id = "".join(random.choices(string.ascii_lowercase, k=8))
        domain_sessions[domain] = get_sticky_session()
    return domain_sessions[domain]

# site-a.com always uses the same IP
proxy_a = get_domain_proxy("site-a.com")
# site-b.com gets a different IP
proxy_b = get_domain_proxy("site-b.com")

最佳实践

1. 将地理位置与目标相匹配

# Target site is US-based? Use US residential IP
us_proxy = "http://user-country-us:pass@gateway.proxy.com:7777"

# Target is Germany? Use DE residential IP
de_proxy = "http://user-country-de:pass@gateway.proxy.com:7777"

地理不匹配的 IP 会触发更多验证码(例如,从尼日利亚 IP 访问美国网站)。

2. 设置切合实际的请求率

import time
import random

def human_pace_requests(urls, proxy):
    results = []
    for url in urls:
        resp = requests.get(url, proxies=proxy, timeout=30)
        results.append(resp)

        # Random delay between requests
        delay = random.uniform(2, 8)
        time.sleep(delay)

    return results
速度 验证码风险
1 请求 /sec 高(机器人模式)
1 请求/5-10 秒 中等的
1 请求/10-30 秒 低(类人)
随机3-15秒 很低

3.使用正确的标题

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                  "AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/126.0.0.0 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "DNT": "1",
    "Connection": "keep-alive",
    "Upgrade-Insecure-Requests": "1",
}

resp = requests.get(url, proxies=proxy, headers=headers)

4. 妥善处理 IP 封禁

def fetch_with_retry(url, max_retries=3):
    for attempt in range(max_retries):
        # New proxy for each retry
        proxy = get_sticky_session()

        try:
            resp = requests.get(url, proxies=proxy, timeout=30)

            if resp.status_code == 403:
                print(f"IP banned, rotating... (attempt {attempt + 1})")
                time.sleep(5)
                continue

            if resp.status_code == 429:
                print(f"Rate limited, backing off...")
                time.sleep(30)
                continue

            return resp

        except requests.exceptions.ProxyError:
            print(f"Proxy failed, rotating...")
            continue

    raise Exception(f"Failed after {max_retries} retries")

5. 预热新IP

def warm_up_proxy(proxy):
    """Visit neutral sites before target to build session trust."""
    warm_urls = [
        "https://www.google.com",
        "https://www.wikipedia.org",
    ]
    for url in warm_urls:
        try:
            requests.get(url, proxies=proxy, timeout=15)
            time.sleep(random.uniform(2, 5))
        except Exception:
            pass

CaptchaAI 整合模式

import requests
import time
import re
import random
import string

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"


def solve_recaptcha(site_url, sitekey):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": site_url,
        "json": 1,
    })
    task_id = resp.json()["request"]

    for _ in range(60):
        time.sleep(5)
        resp = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = resp.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]

    raise TimeoutError("Timeout")


def scrape_url(url, proxy_config):
    """Complete scrape with proxy + CAPTCHA solving."""
    session_id = "".join(random.choices(string.ascii_lowercase, k=8))
    proxy = {
        "http": f"http://user-session-{session_id}:{proxy_config['pass']}@{proxy_config['host']}",
        "https": f"http://user-session-{session_id}:{proxy_config['pass']}@{proxy_config['host']}",
    }

    resp = requests.get(url, proxies=proxy, timeout=30)

    match = re.search(r'data-sitekey="([^"]+)"', resp.text)
    if match:
        token = solve_recaptcha(url, match.group(1))
        resp = requests.post(
            url.replace("/form", "/submit"),
            proxies=proxy,
            data={"g-recaptcha-response": token},
        )

    return resp.text

成本优化

战略 影响
仅将住宅用于验证码较多的网站 与全住宅相比节省 50-70%
通过会话预热降低验证码频率 更少的 CaptchaAI 调用
在受 CAPTCHA 保护的页面之前批量处理页面 需要更少的粘性会话
监控 IP 质量并删除不良池 更高的首次尝试成功率

故障排除

问题 原因 处理方式
每个页面上都有验证码 错误的 IP 池 切换代理提供商或区域
令牌被拒绝 IP 在解决和提交之间轮换 使用粘性会话
407 错误 验证格式错误 检查提供商的确切用户名格式
反应慢 网关过载 尝试非高峰时间或不同的端点
会话在工作流程中过期 粘滞 TTL 太短 请求更长的会话持续时间

常问问题

我需要多少个住宅 IP?

对于中等抓取(1000页/day),任何主要提供商的池都足够了。旋转网关自动处理 IP 管理。

在验证码解决期间我是否会轮换 IP?

绝不。通过令牌提交,在页面加载时保持相同的 IP。任务完成后进行轮换。

旋转比粘性快吗?

每个请求轮换具有较低的延迟(无会话开销)。粘性会为每个请求增加几毫秒的时间。对于 CAPTCHA 工作流程,差异可以忽略不计。


相关指南

  • 光明数据+CaptchaAI
  • 粘性会话与轮换会话
  • 代理质量影响解决率

优化您的代理轮换以减少验证码 —获取您的 CaptchaAI 密钥解决剩下的问题。

该文章已禁用评论。