GeeTest v3 滑块验证码需要两个参数来解决:gt(静态站点标识符)和 challenge(动态会话令牌)。本指南展示了如何从任何页面提取两者并将其提交到 CaptchaAI。
GeeTest v3参数解释
| 范围 | 描述 | 静态/Dynamic | 例子 |
|---|---|---|---|
gt |
站点标识符(32 个字符的十六进制) | 每个站点的静态 | 019924a82c70bb123aae90d483b6a0ed |
challenge |
会话令牌(32 个字符的十六进制) | 每页动态加载 | a3f5c8d2e1b04a6789012345678abcdf |
api_server |
GeeTest API 子域(可选) | 每个站点的静态 | api-na.geetest.com |
gt 值在请求之间保持不变。每次验证码加载时,challenge 值都会发生变化 - 您必须为每次解决尝试提取一个新的验证码。
方法一:拦截注册API调用
大多数 GeeTest v3 实现从注册端点获取质询。响应如下所示:
{
"success": 1,
"challenge": "a3f5c8d2e1b04a6789012345678abcdf",
"gt": "019924a82c70bb123aae90d483b6a0ed",
"new_captcha": true
}
Python(请求)
import requests
import re
session = requests.Session()
html = session.get("https://staging.example.com/qa-login").text
# Find the register endpoint
register_url = re.search(
r'(https?://[^"\']+(?:register|captcha|geetest)[^"\']*)',
html
)
if register_url:
resp = session.get(register_url.group(1)).json()
gt = resp["gt"]
challenge = resp["challenge"]
print(f"gt: {gt}")
print(f"challenge: {challenge}")
JavaScript(Puppeteer网络拦截)
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
let geetestParams = {};
page.on('response', async (response) => {
const url = response.url();
if (url.includes('register') || url.includes('captcha')) {
try {
const json = await response.json();
if (json.gt && json.challenge) {
geetestParams = {
gt: json.gt,
challenge: json.challenge,
};
console.log('Captured GeeTest params:', geetestParams);
}
} catch (e) {}
}
});
await page.goto('https://staging.example.com/qa-login', { waitUntil: 'networkidle2' });
console.log('Final params:', geetestParams);
方法二:从页面源码中提取
有些网站将参数直接嵌入 HTML 或内联脚本中:
import re
# From data attributes
gt_match = re.search(r'data-gt=["\']([a-f0-9]{32})', html)
challenge_match = re.search(r'data-challenge=["\']([a-f0-9]{32})', html)
# From JavaScript variables
if not gt_match:
gt_match = re.search(r'gt\s*[=:]\s*["\']([a-f0-9]{32})', html)
if not challenge_match:
challenge_match = re.search(r'challenge\s*[=:]\s*["\']([a-f0-9]{32})', html)
gt = gt_match.group(1) if gt_match else None
challenge = challenge_match.group(1) if challenge_match else None
print(f"gt={gt}, challenge={challenge}")
方法三:挂钩initGeetest
GeeTest v3 通过 initGeetest() 进行初始化。在页面脚本运行之前拦截它:
// Puppeteer: inject before page scripts
await page.evaluateOnNewDocument(() => {
window.__geetestConfig = null;
const origInit = window.initGeetest;
Object.defineProperty(window, 'initGeetest', {
set(fn) {
this._initGeetest = function(config, callback) {
window.__geetestConfig = config;
console.log('GeeTest config:', JSON.stringify(config));
return fn(config, callback);
};
},
get() { return this._initGeetest; }
});
});
await page.goto('https://staging.example.com/qa-login', { waitUntil: 'networkidle2' });
const config = await page.evaluate(() => window.__geetestConfig);
// config = { gt: "019924a...", challenge: "a3f5c8d...", product: "bind", ... }
用 CaptchaAI 解决 GeeTest v3
Python
import requests
import time
API_KEY = "YOUR_API_KEY"
# Submit
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "geetest",
"gt": gt,
"challenge": challenge,
"pageurl": "https://staging.example.com/qa-login",
"json": "1",
}).json()
if resp["status"] != 1:
raise Exception(f"Submit error: {resp['request']}")
task_id = resp["request"]
# Poll
for _ in range(30):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
solution = result["request"]
print(f"Solution: {solution}")
break
if result["request"] != "CAPCHA_NOT_READY":
raise Exception(f"Error: {result['request']}")
JavaScript
const submit = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: 'YOUR_API_KEY',
method: 'geetest',
gt: geetestParams.gt,
challenge: geetestParams.challenge,
pageurl: 'https://staging.example.com/qa-login',
json: 1,
}
});
const taskId = submit.data.request;
let solution = null;
for (let i = 0; i < 30; i++) {
await new Promise(r => setTimeout(r, 5000));
const poll = await axios.get('https://ocr.captchaai.com/res.php', {
params: { key: 'YOUR_API_KEY', action: 'get', id: taskId, json: 1 }
});
if (poll.data.status === 1) {
solution = poll.data.request;
break;
}
}
console.log('Solution:', solution);
注入GeeTest解决方案
GeeTest v3 的 CaptchaAI 响应包括 challenge、validate 和 seccode:
# solution is a pipe-delimited string or JSON object
# Parse and inject into the form
import json
sol = json.loads(solution) if isinstance(solution, str) else solution
driver.execute_script("""
const form = document.querySelector('form');
function addHidden(name, value) {
let input = form.querySelector(`input[name="${name}"]`);
if (!input) {
input = document.createElement('input');
input.type = 'hidden';
input.name = name;
form.appendChild(input);
}
input.value = value;
}
addHidden('geetest_challenge', arguments[0]);
addHidden('geetest_validate', arguments[1]);
addHidden('geetest_seccode', arguments[2]);
""", sol["challenge"], sol["validate"], sol["seccode"])
故障排除
| 问题 | 原因 | 处理方式 |
|---|---|---|
ERROR_BAD_PARAMETERS |
缺少 gt 或 challenge |
两者都是必需的;提取新鲜值 |
| 陈旧的挑战 | 挑战令牌已过期 | 在提交之前立即提取新的挑战 |
gt 值错误 |
从不同网站复制的 | gt 是特定于站点的;从目标中重新提取 |
| 解决方案被站点拒绝 | 挑战在解决期间过期 | 减少提取和提交之间的时间 |
常问问题
GeeTest 挑战的有效期是多长?
通常为 60-120 秒。提取挑战并立即提交给 CaptchaAI。
GeeTest v3 和 v4 有什么区别?
GeeTest v3 使用 gt/res.php 参数和滑块。 GeeTest v4使用captcha_id,并具有多种挑战类型(点击、匹配、滑动)。
使用 CaptchaAI 解决 GeeTest v3 验证码
获取您的 API 密钥:验证码网站。