网格图像验证码(Grid Image CAPTCHA)识别失败,多半不是引擎问题,而是格式、坐标或超时没对齐。先看排查清单,再逐条处理。
3 秒自查:网格验证码报错排查清单
| 排查项 | 处理方式 |
|---|---|
| 图片格式? | 只用 PNG 或 JPEG,Base64 编码正确 |
| 图片体积? | 控制在 600 KB 以内 |
| 网格截全了? | 连边框一起截,留几像素边距 |
| 图片够清晰? | 不模糊、不等比例缩小 |
| 索引对齐? | API 返回从 1 开始,转成从 0 开始 |
| 在 iframe 里? | 先切换 iframe,再定位格子 |
| 已经过期? | 截图后立刻提交 |
清单都过了还报错?直接跳到下面对应的错误码小节。
提交阶段的常见错误:图片格式与体积
ERROR_WRONG_FILE_EXTENSION
原因: 上传的文件不是有效的图片格式:
- 只用 PNG 或 JPEG 格式
- 确认 Base64 字符串编码正确
- 发送前去掉
data:image/...;base64,前缀
# WRONG — includes data URI prefix
body = "data:image/png;base64,iVBORw0KGgo..."
# CORRECT — raw base64 only
body = "iVBORw0KGgo..."
ERROR_TOO_BIG_CAPTCHA_FILESIZE
原因: 图片超过了最大文件体积(通常 600 KB):
from PIL import Image
import io
import base64
# Resize if too large
img = Image.open("captcha.png")
if img.width > 600:
ratio = 600 / img.width
img = img.resize((600, int(img.height * ratio)), Image.LANCZOS)
buffer = io.BytesIO()
img.save(buffer, format="PNG")
b64 = base64.b64encode(buffer.getvalue()).decode()
ERROR_ZERO_CAPTCHA_FILESIZE
原因: 文件为空,或图片提取失败:
- 提取前先确认图片元素已经加载完成
- 检查
src属性不是空的 - 给懒加载的图片留出等待时间
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# Wait for image to load
WebDriverWait(driver, 10).until(
lambda d: d.find_element(By.CSS_SELECTOR, ".captcha img").get_attribute("complete") == "true"
)
识别结果错误:为什么选错了格子
ERROR_CAPTCHA_UNSOLVABLE
原因: 图片太模糊、太扭曲,或图中物体本身难以辨认:
- 按原始分辨率截图,不要缩小
- 确认没有遮罩或水印挡住网格
- 换一张新验证码重试(有些挑战本身就模棱两可)
这两个错误常一起出现:先排除压缩导致的模糊,再检查截图范围是否完整。
选中了错误的格子
原因: 图片质量差,或只截取了部分区域:
- 截图要包含整个验证码元素,连边框一起截
- 不要裁得太紧,留出几像素的边距
- 保存截图后手动打开看一眼,确认截对了
# Take a proper element screenshot
captcha_el = driver.find_element(By.CSS_SELECTOR, "#captcha-container")
captcha_el.screenshot("debug_captcha.png")
# Open and check manually
from PIL import Image
Image.open("debug_captcha.png").show()
结果应用与点击错误
索引错位:差一错误
原因: API 返回的索引从 1 开始,数组下标却是从 0 开始,两边没对齐。
# API returns "1,3,5" (1-based)
solution = "1,3,5"
indices = [int(i) for i in solution.split(",")]
# DON'T: use directly as array index
# cells[1], cells[3], cells[5] ← WRONG (off by one)
# DO: convert to 0-based
for idx in indices:
cells[idx - 1].click() # 1→0, 3→2, 5→4
点了格子,页面却没反应
原因: 点击目标不对 —— 可能被遮罩挡住、验证码在 iframe 里,或用了 shadow DOM:
# Check if captcha is in an iframe
iframes = driver.find_elements(By.TAG_NAME, "iframe")
for iframe in iframes:
if "captcha" in iframe.get_attribute("src").lower():
driver.switch_to.frame(iframe)
break
# Now find and click cells
cells = driver.find_elements(By.CSS_SELECTOR, ".grid-cell")
动态网格——点完之后图块又变了
原因: reCAPTCHA 风格的动态网格会在点击后替换图块——改用 token 方式提交:
# Token method handles dynamic grids automatically
response = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "SITE_KEY",
"pageurl": "https://example.com",
"json": 1
})
动态网格没必要死磕图像点击,切 token 方式最省事。
超时与轮询错误
结果还没返回,验证码先过期了
原因: 网格验证码通常 2~3 分钟就会过期:
- 截图后立刻提交,别攒着
- 如果识别耗时超过 60 秒,直接刷新重试
卡在 CAPCHA_NOT_READY,一直轮询不停
原因: 任务大概率静默失败了——给轮询设最大重试次数:
for attempt 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.get("status") == 1:
return result["request"]
if result.get("request") not in ["CAPCHA_NOT_READY"]:
break # Actual error, stop polling
raise Exception("Grid captcha solve failed — refresh and retry")
国内环境下的额外排查建议
国内跑脚本时,Pillow、Selenium 装到一半超时也会间接触发上述错误,建议换国内镜像。不少国内后台、OA 系统仍用图片或网格验证码,排查思路通用。
pip install卡住时换镜像,如pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pillow selenium。
常见问题
PNG 和 JPEG,哪种格式识别更准?
PNG 无损,边界最清晰;JPEG 压缩率一高会糊边界,拉低识别率。
提交网格图片一定要带文字说明吗?
method=post 搭配 recaptcha=1 不需要;method=bls 必须带,否则报错。
一直卡在 CAPCHA_NOT_READY,是我的任务丢了吗?
大概率静默失败,不是账号或图片问题。给轮询设最大重试次数,超过就直接重新提交。
格子明明选对了,点击却没反应,怎么排查?
先确认验证码是不是嵌在 iframe 里——大多数点击失效都是脚本操作了外层 DOM。
网格验证码识别失败,会浪费我的线程配额吗?
不会。CaptchaAI 按并发线程计费,一个线程处理完一个任务(无论成败)就能接下一个,BASIC 套餐($15 / 月,5 个线程)同样适用。