CAPTCHA 解决有四个延迟组件:提交请求、队列等待、求解器执行和轮询检索。您无法控制求解器的执行时间,但可以优化其他所有内容。
按验证码类型划分的基线延迟
| 验证码类型 | 典型求解时间 | 最好的实现 |
|---|---|---|
| 图片/OCR | 2-5秒 | 1-3秒 |
| reCAPTCHA v2 | 15-30秒 | 10-20秒 |
| reCAPTCHA v3 | 10-20秒 | 8-15秒 |
| Cloudflare Turnstile | 10-25秒 | 8-15秒 |
| GeeTest v3 | 15-30秒 | 10-20秒 |
“最佳可实现”列反映了应用以下优化后您获得的结果。
1.优化轮询间隔
当求解在轮询之间完成时,默认的 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 连接,而不是为每个轮询打开新连接:
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. 预取验证码
在需要令牌之前提交验证码任务。当您的抓取工具处理第 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.使用正确的验证码方法
CaptchaAI 有时支持针对特定场景的更快方法:
| 设想 | 慢速法 | 更快的替代方案 |
|---|---|---|
| reCAPTCHA v2 具有已知回调 | userrecaptcha + 民意调查 |
userrecaptcha 和 pingback(回调 URL) |
| 图片文字验证码 | base64 高分辨率 |
如果仅包含数字,则 base64 与 numeric=1 |
| reCAPTCHA v3 | 默认 min_score |
将 min_score 设置为实际需要的阈值(越低=越快) |
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:pass@1.2.3.4:8080"
data["proxytype"] = "HTTP"
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",
})
求解完成后,CaptchaAI 将结果发送到您的 URL。不需要轮询循环。这是最快的检索方法。
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")
故障排除
| 问题 | 原因 | 处理方式 |
|---|---|---|
| 轮询延迟不变 | 仍然使用 requests.get() 没有会话 |
切换至session.get() |
| 预取令牌在使用前过期 | 处理时间太长 | 减少预取窗口或在接近使用时提交 |
| 回调 URL 从不接收数据 | 无法从 CaptchaAI 访问服务器 | 确保公共 URL、正确的防火墙规则 |
| 更快的轮询会导致速率限制 | 轮询过于激进(< 2 秒) | 保持最小间隔为 3 秒 |
常问问题
最大的单一优化是什么?
预取。它将求解时间与处理时间重叠,有效地将顺序工作流程的感知延迟减少到接近于零。
自适应轮询对图像验证码有帮助吗?
不太如此。图像验证码会在 2-5 秒内解决,因此 3 秒时的第一次轮询通常会捕获它们。 reCAPTCHA 的改进更为明显(15-30 秒)。
使用 CaptchaAI 获得最快的验证码解决
获取您的 API 密钥:验证码网站。