并非所有验证码都是 reCAPTCHA 或标准文本图像。自定义验证码需要创造性的方法来提取和提交参数。
识别自定义验证码
| 类型 | 特征 | 方法 |
|---|---|---|
| 滑块验证码 | 拖至指定位置 | 截图为图片,使用文字说明 |
| 拼图(拼图) | 拖动一块以适合 | 可以映射到 GeeTest 式的解决方案 |
| 音频验证码 | 听并输入 | 提交音频文件 |
| 旋转图像 | 旋转至正确方向 | 截图+说明 |
| 选择订单 | 按顺序单击项目 | 使用图像网格方法 |
| 数学方程 | 解决算术问题 | 使用calc=1参数 |
| 定制互动 | 站点特定的 JS 小部件 | 截图+文字说明 |
提交带有说明的自定义图像
对于任何视觉验证码,请将其屏幕截图并提供说明:
import requests
import base64
import time
import os
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
def solve_custom_captcha(image_b64, instructions):
"""Solve any visual CAPTCHA using image + text instructions."""
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "base64",
"body": image_b64,
"textinstructions": instructions,
"json": 1,
}, timeout=30)
result = resp.json()
if result.get("status") != 1:
raise RuntimeError(result.get("request"))
task_id = result["request"]
time.sleep(10)
for _ in range(30):
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": task_id, "json": 1,
}, timeout=15)
data = resp.json()
if data.get("status") == 1:
return data["request"]
if data["request"] != "CAPCHA_NOT_READY":
raise RuntimeError(data["request"])
time.sleep(5)
raise TimeoutError("Solve timeout")
滑块位置验证码
需要将滑块拖动到特定位置的验证码:
# slider_captcha.py
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
def solve_slider_captcha(driver, captcha_selector):
"""Screenshot slider CAPTCHA and solve via CaptchaAI."""
captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
image_b64 = captcha.screenshot_as_base64
result = solve_custom_captcha(
image_b64,
"What pixel position should the slider be dragged to? "
"Return only the X offset number."
)
try:
offset = int(result)
except ValueError:
return False
# Drag slider to position
slider = driver.find_element(By.CSS_SELECTOR, ".slider-handle")
ActionChains(driver).click_and_hold(slider).move_by_offset(offset, 0).release().perform()
return True
旋转验证码
必须将图像旋转到正确方向的验证码:
# rotation_captcha.py
def solve_rotation_captcha(driver, captcha_selector):
"""Solve rotation CAPTCHA."""
captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
image_b64 = captcha.screenshot_as_base64
result = solve_custom_captcha(
image_b64,
"How many degrees should this image be rotated clockwise "
"to be in the correct upright orientation? Return only the number."
)
try:
degrees = int(result)
except ValueError:
return False
# Click rotation button the correct number of times
rotate_btn = driver.find_element(By.CSS_SELECTOR, ".rotate-button")
clicks = degrees // 90 # Each click rotates 90 degrees
for _ in range(clicks):
rotate_btn.click()
time.sleep(0.3)
return True
选择订单验证码
必须按特定顺序单击项目的验证码:
# order_captcha.py
def solve_order_captcha(driver, captcha_selector, item_selector):
"""Solve click-in-order CAPTCHA."""
captcha = driver.find_element(By.CSS_SELECTOR, captcha_selector)
image_b64 = captcha.screenshot_as_base64
result = solve_custom_captcha(
image_b64,
"What is the correct order? Return as comma-separated "
"numbers (1-indexed) representing positions left-to-right, top-to-bottom."
)
# Parse order
try:
order = [int(x.strip()) for x in result.split(",")]
except ValueError:
return False
# Click items in order
items = driver.find_elements(By.CSS_SELECTOR, item_selector)
for idx in order:
if 1 <= idx <= len(items):
items[idx - 1].click()
time.sleep(0.5)
return True
音频验证码
一些网站提供音频替代方案:
# audio_captcha.py
import requests
def solve_audio_captcha(audio_url):
"""Download and solve an audio CAPTCHA."""
# Download audio
resp = requests.get(audio_url, timeout=30)
audio_b64 = base64.b64encode(resp.content).decode("ascii")
# Submit as image with instructions
# CaptchaAI may support audio via the base64 method
result = solve_custom_captcha(
audio_b64,
"This is an audio CAPTCHA. Transcribe the spoken characters."
)
return result
自定义小部件验证码
对于完全自定义的验证码小部件:
# custom_widget.py
from selenium import webdriver
from selenium.webdriver.common.by import By
def handle_custom_widget(driver, widget_selector):
"""Handle an unknown custom CAPTCHA widget."""
# Step 1: Screenshot the entire widget
widget = driver.find_element(By.CSS_SELECTOR, widget_selector)
image_b64 = widget.screenshot_as_base64
# Step 2: Get any visible instructions
try:
instructions_el = widget.find_element(By.CSS_SELECTOR, ".instructions, .prompt, p")
visible_instructions = instructions_el.text
except Exception:
visible_instructions = "Solve this CAPTCHA"
# Step 3: Submit with descriptive instructions
result = solve_custom_captcha(
image_b64,
f"CAPTCHA instructions: {visible_instructions}. "
f"Return the answer text."
)
# Step 4: Try to submit result
try:
input_el = widget.find_element(By.CSS_SELECTOR, "input")
input_el.clear()
input_el.send_keys(result)
except Exception:
# No input — try clicking based on result
driver.execute_script("""
var input = document.querySelector('input[name*="captcha"]');
if (input) input.value = arguments[0];
""", result)
return result
验证码类型检测
# detector.py
import re
def detect_captcha_type(page_html):
"""Detect which CAPTCHA type is on a page."""
checks = {
"recaptcha_v2": r'data-sitekey.*g-recaptcha',
"recaptcha_v3": r'recaptcha/api\.js\?render=',
"turnstile": r'cf-turnstile|challenges\.cloudflare\.com/turnstile',
"geetest": r'gt\b.*challenge|geetest',
"bls": r'method.*bls|bls-captcha',
"image_text": r'captcha.*\.(png|jpg|gif|jpeg)',
"slider": r'slider.*captcha|slide.*verify',
"audio": r'audio.*captcha|captcha.*audio',
}
detected = []
for captcha_type, pattern in checks.items():
if re.search(pattern, page_html, re.IGNORECASE):
detected.append(captcha_type)
return detected if detected else ["unknown"]
故障排除
| 问题 | 原因 | 处理方式 |
|---|---|---|
ERROR_CAPTCHA_UNSOLVABLE |
图片不清楚或说明模糊 | 提高屏幕截图质量和说明 |
| 答案格式错误 | 求解器返回描述而不是值 | 具体一点:“仅返回数字” |
| 自定义小部件未捕获 | 视口外的元素 | 滚动到屏幕截图之前的元素 |
| 交互失败 | 点击坐标错误 | 仔细地将解决方案映射到实际的 UI 元素 |
常问问题
CaptchaAI可以解决任何验证码类型吗?
CaptchaAI 原生支持 27,500 多种验证码类型。对于真正新颖的自定义验证码,图像 + 文本说明方法提供了最佳覆盖范围。
如果自定义验证码频繁更改怎么办?
使用类型检测功能来识别当前的挑战并路由到适当的求解器。
如何获得对新验证码类型的支持?
请联系 CaptchaAI 支持人员并提供示例图像和站点 URL。可以将新类型添加到平台中。
相关指南
- 多角色解决策略
- Base64 编码最佳实践
解决任何验证码 -以 CaptchaAI 开头.