轮换自有服务器基础设施为每个请求(或每个会话)分配一个新的真实用户 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 密钥解决剩下的问题。