粘性会话在设定的持续时间内保留相同的 IP。轮换会话为每个请求分配一个新的 IP。选择错误的验证码会提高验证码率并浪费 API 积分。
每种模式如何运作
STICKY SESSION:
Request 1 ──▶ IP: 192.168.1.50 ──▶ site.com/login
Request 2 ──▶ IP: 192.168.1.50 ──▶ site.com/dashboard
Request 3 ──▶ IP: 192.168.1.50 ──▶ site.com/account
(Same IP for all requests in the session window)
ROTATING SESSION:
Request 1 ──▶ IP: 192.168.1.50 ──▶ site.com/page1
Request 2 ──▶ IP: 10.0.0.77 ──▶ site.com/page2
Request 3 ──▶ IP: 172.16.5.22 ──▶ site.com/page3
(Different IP per request)
头对头比较
| 因素 | 黏 | 旋转 |
|---|---|---|
| 每个请求的IP | 同样1-30分钟 | 新的每个请求 |
| 会话一致性 | 高的 | 没有任何 |
| 验证码率(多步骤流程) | 低(5-10%) | 高 (30-50%) |
| 验证码率(单页) | 中(10-20%) | 低(5-10%) |
| 令牌有效性 | 更高——相同IP | 不匹配的风险 |
| 速度 | 快速(重用连接) | 较慢(新连接) |
| 禁止风险 | 如果被标记则更高 | 低——每次都有新IP |
| 成本 | 相同或稍多 | 相同的 |
| 最适合 | 登录、结账、授权 | 批量抓取、搜索 |
当粘性会话获胜时
多步骤工作流程
CAPTCHA 根据请求的 IP 验证令牌。如果您的 IP 在解决和提交之间发生变化,则令牌可能会被拒绝。
import requests
import time
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
# Sticky session: same IP for the entire login flow
STICKY_PROXY = {
"http": "http://user-session-abc123:pass@proxy.example.com:5000",
"https": "http://user-session-abc123:pass@proxy.example.com:5000",
}
session = requests.Session()
session.proxies = STICKY_PROXY
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
})
def login_with_captcha(url, sitekey, username, password):
"""Full login flow — MUST use same IP throughout."""
# Step 1: Load login page (IP: 192.168.1.50)
session.get(url)
# Step 2: Solve CAPTCHA (solved against IP: 192.168.1.50)
token = solve_recaptcha(sitekey, url)
# Step 3: Submit login (MUST be IP: 192.168.1.50)
resp = session.post(url, data={
"username": username,
"password": password,
"g-recaptcha-response": token,
})
return resp.status_code == 200
def solve_recaptcha(sitekey, pageurl):
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
"key": CAPTCHAAI_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1,
})
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
data = result.json()
if data["request"] != "CAPCHA_NOT_READY":
return data["request"]
raise TimeoutError("CAPTCHA solve timeout")
为什么 IP 一致性很重要
Sticky session:
1. Browser loads page → IP: 5.5.5.5
2. CAPTCHA solved → Token bound to session
3. Form submitted → IP: 5.5.5.5 ✅ Token accepted
Rotating session:
1. Browser loads page → IP: 5.5.5.5
2. CAPTCHA solved → Token bound to session
3. Form submitted → IP: 9.9.9.9 ❌ Token may be rejected
当轮流会议获胜时
批量页面抓取
每个页面都是独立的。轮换 IP 可将请求分散到更大的池中,从而减少每个 IP 的检测。
import concurrent.futures
ROTATING_PROXY = {
"http": "http://user:pass@rotating.proxy.example.com:5000",
"https": "http://user:pass@rotating.proxy.example.com:5000",
}
def scrape_page(url):
"""Each request gets a fresh IP automatically."""
resp = requests.get(
url,
proxies=ROTATING_PROXY,
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},
timeout=30,
)
if resp.status_code == 200:
return url, resp.text
return url, None
urls = [f"https://example.com/products?page={i}" for i in range(1, 501)]
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as pool:
results = list(pool.map(scrape_page, urls))
success = sum(1 for _, html in results if html)
print(f"Scraped: {success}/{len(urls)}")
搜索引擎抓取
搜索引擎跟踪每个 IP 的查询量。轮换避免速率限制:
def scrape_search(query, pages=10):
results = []
for page in range(pages):
# Each request → new IP
resp = requests.get(
"https://search-engine.example.com/search",
params={"q": query, "start": page * 10},
proxies=ROTATING_PROXY,
timeout=20,
)
results.append(resp.text)
time.sleep(2)
return results
混合策略
在同一管道中使用两种模式:
class HybridProxyManager:
"""Sticky for multi-step flows, rotating for single requests."""
def __init__(self, provider_host, username, password, port=5000):
self.host = provider_host
self.username = username
self.password = password
self.port = port
def get_rotating_proxy(self):
return {
"http": f"http://{self.username}:{self.password}@{self.host}:{self.port}",
"https": f"http://{self.username}:{self.password}@{self.host}:{self.port}",
}
def get_sticky_proxy(self, session_id, duration_min=10):
sticky_user = f"{self.username}-session-{session_id}-ttl-{duration_min}"
return {
"http": f"http://{sticky_user}:{self.password}@{self.host}:{self.port}",
"https": f"http://{sticky_user}:{self.password}@{self.host}:{self.port}",
}
proxy_mgr = HybridProxyManager("proxy.example.com", "user", "pass")
def scrape_with_auto_strategy(url, needs_login=False):
if needs_login:
# Multi-step → sticky
import uuid
session_id = uuid.uuid4().hex[:8]
proxy = proxy_mgr.get_sticky_proxy(session_id)
else:
# Single page → rotating
proxy = proxy_mgr.get_rotating_proxy()
return requests.get(url, proxies=proxy, timeout=30)
Node.js 实现
const axios = require("axios");
const CAPTCHAAI_KEY = "YOUR_API_KEY";
const PROXY_HOST = "proxy.example.com";
const PROXY_PORT = 5000;
function getProxy(mode, sessionId = null) {
const user =
mode === "sticky" ? `user-session-${sessionId}` : "user";
return {
proxy: {
host: PROXY_HOST,
port: PROXY_PORT,
auth: { username: user, password: "pass" },
},
};
}
// Rotating: bulk scrape
async function scrapePages(urls) {
const results = [];
for (const url of urls) {
const config = getProxy("rotating");
const resp = await axios.get(url, { ...config, timeout: 30000 });
results.push({ url, data: resp.data });
}
return results;
}
// Sticky: login flow
async function loginFlow(loginUrl, sitekey, credentials) {
const sessionId = Date.now().toString(36);
const config = getProxy("sticky", sessionId);
// Step 1: Load page
await axios.get(loginUrl, config);
// Step 2: Solve CAPTCHA
const submitResp = await axios.post(
"https://ocr.captchaai.com/in.php",
null,
{
params: {
key: CAPTCHAAI_KEY,
method: "userrecaptcha",
googlekey: sitekey,
pageurl: loginUrl,
json: 1,
},
}
);
const taskId = submitResp.data.request;
let token;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const res = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: CAPTCHAAI_KEY, action: "get", id: taskId, json: 1 },
});
if (res.data.request !== "CAPCHA_NOT_READY") {
token = res.data.request;
break;
}
}
// Step 3: Submit with same IP
return axios.post(
loginUrl,
{
...credentials,
"g-recaptcha-response": token,
},
config
);
}
决策矩阵
| 工作流程 | 受到推崇的 | 为什么 |
|---|---|---|
| 登录/注册 | 黏 | 令牌与IP绑定 |
| 结帐/付款 | 黏 | 会话cookie需要相同的IP |
| 批量页面抓取 | 旋转 | 分配负载 |
| 搜索引擎抓取 | 旋转 | 避免每个 IP 的速率限制 |
| API轮询(同一端点) | 旋转 | 减少每个 IP 特征 |
| 多页面导航 | 黏 | 通过 IP 跟踪 Cookie |
| 价格监控 | 旋转 | 许多独立的请求 |
| 账户管理 | 黏 | 会话完整性 |
| 使用验证码提交表单 | 黏 | Token-IP绑定 |
| 广告验证 | 旋转 | 模拟不同的用户 |
粘性会话持续时间
| 期间 | 最适合 | 风险 |
|---|---|---|
| 1分钟 | 快速表单提交 | 可能会在流动中过期 |
| 5分钟 | 标准登录+操作 | 平衡性好 |
| 10分钟 | 复杂的多页面流程 | 中等禁令风险 |
| 30分钟 | 扩展浏览会话 | 封禁风险较高 |
| 60分钟 | 多头账户操作 | 最高禁令风险 |
经验法则: 将粘性持续时间设置为预期流动时间的 2 倍。
故障排除
| 问题 | 原因 | 处理方式 |
|---|---|---|
| 解决后验证码令牌被拒绝 | 解决和提交之间 IP 发生变化 | 切换到粘性会话 |
| 单页验证码率高 | 同一粘性 IP 访问过多页面 | 切换到旋转 |
| 会话cookie丢失 | 粘性会话已过期 | 增加 TTL 持续时间 |
| 慢速旋转性能 | 每个新 IP 的连接开销 | 使用连接池 |
| 粘性会话中禁止的 IP | 所有请求共享标记的IP | 减少会话 TTL 或增加延迟 |
常问问题
我可以在一个项目中混合粘性和旋转吗?
是的。使用混合方法——粘性用于身份验证流程,轮换用于数据收集。大多数代理提供商在同一计划上支持这两种模式。
粘性会话能保证同一个IP吗?
大多数提供商都会在 TTL 窗口内保证它。如果 IP 变得不可用(运营商重新分配、池轮换),则会分配新的 IP。
哪种模式更便宜?
价格相同——无论模式如何,您都按 GB 或每个请求付费。成本差异来自于验证码费率:错误模式 → 更多验证码 → 更高的 CaptchaAI 花费。
如何设置与代理提供商的粘性会话?
大多数在用户名中使用会话 ID:user-session-abc123。检查您的提供商的文档以了解确切的格式。我们涵盖明亮的数据,智能代理, 和氧化实验室在专门的指南中。
相关指南
- 轮换自有服务器基础设施
- 代理质量影响解决率
- 浏览器会话持久性
将您的代理策略与您的工作流程相匹配 -获取您的 CaptchaAI 密钥在任何会话模式下处理验证码。