reCAPTCHA v2 要等十几二十秒才出 token,问题往往不在求解器,而在轮询、连接和调度方式。求解要经过四步:提交、排队、执行、轮询取回,执行时间你控制不了,能压缩的是:
- 轮询策略
- 连接方式
- 调度方式
各类型验证码的官方处理时长
以下是官方处理时长上限,实测会因站点和难度波动。这是求解器的天花板,优化只省提交、排队、轮询三步的时间。
| 验证码类型 | 官方处理时长上限 | 成功率 |
|---|---|---|
| 图片/OCR 验证码 | < 0.5 秒 | 高 |
| reCAPTCHA v3 | < 4 秒 | 高 |
| Cloudflare Turnstile | < 10 秒 | 高 |
| GeeTest v3 | < 12 秒 | 高 |
| reCAPTCHA v2 | < 60 秒 | 高 |
1. 自适应轮询:告别固定 5 秒等待
固定 5 秒轮询一次,结果早出来了你还在傻等。思路很简单:
- 前 4 次轮询用 3 秒间隔
- 之后放慢到 5 秒,避免频繁请求
Python
import time
import requests
API_KEY = "YOUR_API_KEY"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def adaptive_poll(task_id, timeout=120):
"""Start polling at 3s, increase to 5s after 4 polls."""
start = time.time()
interval = 3 # start aggressive
polls = 0
while time.time() - start < timeout:
time.sleep(interval)
polls += 1
resp = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get",
"id": task_id, "json": "1"
}).json()
if resp["status"] == 1:
elapsed = time.time() - start
print(f"Solved in {elapsed:.1f}s ({polls} polls)")
return resp["request"]
if resp["request"] != "CAPCHA_NOT_READY":
raise Exception(resp["request"])
# Back off after initial fast polls
if polls >= 4:
interval = 5
raise TimeoutError(f"Task {task_id} timed out")
JavaScript
async function adaptivePoll(taskId, apiKey, timeout = 120000) {
const start = Date.now();
let interval = 3000;
let polls = 0;
while (Date.now() - start < timeout) {
await new Promise(r => setTimeout(r, interval));
polls++;
const resp = await fetch(
`https://ocr.captchaai.com/res.php?key=${apiKey}&action=get&id=${taskId}&json=1`
);
const data = await resp.json();
if (data.status === 1) {
console.log(`Solved in ${((Date.now() - start) / 1000).toFixed(1)}s (${polls} polls)`);
return data.request;
}
if (data.request !== 'CAPCHA_NOT_READY') {
throw new Error(data.request);
}
if (polls >= 4) interval = 5000;
}
throw new Error(`Task ${taskId} timed out`);
}
跟固定 5 秒轮询一次相比,平均能省下 1-4 秒。
2. 连接池:省掉重复握手的时间
不要每次轮询都新开一个 HTTP 连接,复用已有连接:
- 跳过重复的 TCP 握手
- 跳过重复的 TLS 协商
Python
session = requests.Session()
# Use session.get() and session.post() instead of requests.get/post
# The session reuses TCP connections automatically
JavaScript (Node.js)
const { Agent } = require('http');
const axios = require('axios');
const client = axios.create({
httpAgent: new Agent({ keepAlive: true, maxSockets: 10 }),
timeout: 10000,
});
// Use client.get() and client.post() for all API calls
跳过 TCP/TLS 握手,每个请求大约能省下 50-100 毫秒。
3. 预取验证码:让求解和处理并行跑
在真正需要 token 前就提交任务,处理第 N 页时顺手提交第 N+1 页的验证码:
from concurrent.futures import ThreadPoolExecutor
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
def prefetch_submit(sitekey, page_url):
resp = session.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
})
data = resp.json()
if data["status"] == 1:
return data["request"]
raise Exception(data["request"])
# Submit next page's CAPTCHA while processing current page
with ThreadPoolExecutor(max_workers=2) as pool:
# Submit CAPTCHA for page 2 while processing page 1
future_task = pool.submit(prefetch_submit, "6Le-SITEKEY", "https://example.com/page/2")
# Process page 1...
process_page(current_data)
# Now get the pre-submitted task ID and poll
task_id = future_task.result()
token = adaptive_poll(task_id)
让求解时间和处理时间叠在一起跑,直接抹掉这段等待。
4. 用对方法:有些场景本来就有更快的路径
部分场景有更快的调用方法:
- reCAPTCHA v2 有固定回调地址:
userrecaptcha配合pingback,别再轮询 - 纯数字图片验证码:
base64带上numeric=1,比默认高分辨率模式快
5. 该用代理才用代理,别当默认项
代理转发会增加延迟,只有目标站点要求特定 IP 时才带上代理参数:
# Without proxy — faster for most use cases
data = {
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
}
# With proxy — only when required
data["proxy"] = "user:[email protected]:8080"
data["proxytype"] = "HTTP"
代理不是默认项——跳过它反而更快,只在目标站点明确要求特定 IP 时才加上。
6. 用回调 URL 代替轮询,直接省掉这一步
pingback 参数能让你完全不用轮询:
resp = session.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
"pingback": "https://your-server.com/captcha-callback",
})
求解完成后结果自动推送到你的地址,不需要轮询循环——最快的取回方式。
7. 给优化效果做基准测试
凭感觉判断"是不是变快了"不靠谱,跑一遍基准测试:
import statistics
def benchmark(solve_func, iterations=20):
times = []
for i in range(iterations):
start = time.time()
try:
solve_func()
times.append(time.time() - start)
except Exception:
pass
if times:
print(f"Samples: {len(times)}/{iterations}")
print(f"Mean: {statistics.mean(times):.1f}s")
print(f"Median: {statistics.median(times):.1f}s")
print(f"P95: {sorted(times)[int(len(times)*0.95)]:.1f}s")
print(f"Min: {min(times):.1f}s")
print(f"Max: {max(times):.1f}s")
常见问题
预取和连接池能一起用吗?
可以,两者不冲突:预取解决排队等待,连接池省握手时间。
自适应轮询对图片验证码有用吗?
帮助有限。图片验证码通常 0.5 秒内出结果,3 秒首次轮询基本都能命中,reCAPTCHA v2 受益更明显。
国内访问 CaptchaAI 接口延迟会很高吗?
会多一些往返时延,跟验证码类型无关。reCAPTCHA 还要加载 Google 脚本,部分网络下可能不稳定,建议先跑基准测试。
轮询间隔越低越好吗?
不是。低于 3 秒容易触发限流,3 秒起步、稳定后退避到 5 秒较安全。
常见故障排查
- 轮询延迟不变:没走 session——换成
session.get() - 预取的 token 过期:处理耗时太长——缩短预取窗口
- 回调收不到数据:服务器不可公网访问——检查防火墙规则
- 触发限流:轮询间隔 < 2 秒——保持 3 秒以上
用 CaptchaAI 拿到更快的验证码识别速度
前往 CaptchaAI 官网 获取 API Key,把这些方法用起来。