Explainers

数学和逻辑验证码类型解释

如果你的自动化脚本卡在一个要你心算的文本框——比如“3 加 5 等于几”——那大概率不是 reCAPTCHA,也不是 Turnstile,而是最古老的一类验证码:数学验证码(Math CAPTCHA)。逻辑验证码(Logic CAPTCHA)与它同宗同源,只是用“天空是什么颜色”这类常识问题代替了算术题。这类挑战不需要接入第三方 API,因此在 WordPress 联系表单、老旧后台系统里至今随处可见。


数学和逻辑验证码有哪几种类型

这五种在真实站点上出现频率最高,按识别难度从低到高排:

类型 说明 示例 技术实现
1. 基础算术 简单的加减乘题,纯文本或图片皆有 “3 加 5 等于几?”“6 乘以 7 是多少?” 纯 HTML 文本可直接正则解析;图片版需先 OCR
2. 图片渲染型 方程式渲染成变形图片,防止脚本直接抓取文本 数字带噪点背景、字体扭曲变形 先 OCR 识别出方程式,再算出答案
3. 文字数字型 数字拼成英文单词,而非阿拉伯数字 “What is seven plus three?” 需 NLP 把单词解析成数字,再计算
4. 常识 / 逻辑题 不算数,考的是常识判断 “草是什么颜色的?”“狗有几条腿?” 需知识库或语言模型,题目通常来自固定题库
5. 数列 / 规律 给一串数字,填出下一个值 “2、4、6、8,接下来是?” 需做规律识别(等差数列、斐波那契数列等)

为什么这么老的验证码还没被淘汰

数学验证码几乎是成本最低的人机识别方式,这也是它至今没被替换掉的原因:

  1. 零依赖 —— 不接第三方 API,一个后端 session 就能搞定。
  2. WordPress 生态 —— “Math CAPTCHA”、“Really Simple CAPTCHA” 插件安装量很大,跨境独立站商家也常用类似心算题拦截垃圾询盘。
  3. 摩擦小 —— 对真实用户来说,心算比在图片九宫格里挑目标快得多。
  4. 无障碍友好 —— 纯文本版本能被屏幕阅读器正常读出,图片验证码做不到。
  5. 历史包袱 —— 大量老系统在 reCAPTCHA、Turnstile 出现之前就已上线,后续也没动力升级。

国内网站更常见 GeeTest(极验)、网易易盾这类滑块验证;数学验证码多见于海外 SaaS 后台或老旧系统,容易被自动化流程忽略,直到脚本报错才发现。


数学验证码与主流验证码类型的对比

和主流方案放在一起比一比,更容易看出该在什么场景下选它:

特征 数学验证码 reCAPTCHA v2 hCaptcha 滑块验证码
用户摩擦 低(心算即可) 中(图片选择) 中(图片选择) 低(单次拖动)
抗机器人能力 很低 中等
无障碍支持 好(文本版本) 差(依赖视觉) 差(依赖视觉) 差(依赖操作精度)
成本 免费(自建) 提供免费额度 提供免费额度 视方案而定
常见场景 WordPress、联系表单 登录、注册 登录、注册 电商、亚洲市场

服务端是怎么生成和校验数学验证码的

前端形式不管怎么变,后端逻辑大同小异:生成题目、存答案、等提交后比对。

纯文本版本的流程

Server generates random equation (e.g., "7 + 3")
    ↓
Stores answer (10) in server-side session
    ↓
Renders equation as HTML text or image
    ↓
User submits answer via form field
    ↓
Server compares submitted answer to stored answer
    ↓
Match → Form submitted     Mismatch → Error shown

图片版本的流程

图片版本只是多了一步——把方程式画成图片:

Server generates random equation
    ↓
Renders equation into a distorted image (noise, lines, color shifts)
    ↓
Image served to client via <img> tag
    ↓
User reads image, computes answer, types in form field
    ↓
Server validates submitted answer

如何在自动化脚本里识别出数学验证码

写解题逻辑之前,先让脚本自动判断页面上是不是数学验证码。下面两个函数逻辑一致:正则匹配纯文本题目,扫描 alt 属性里带 captcha/math/verify 的图片,再检查常识题的关键词。

Python 检测

import requests
from bs4 import BeautifulSoup
import re

def detect_math_captcha(url):
    """Detect common math CAPTCHA patterns on a page."""
    response = requests.get(url, timeout=10)
    soup = BeautifulSoup(response.text, "html.parser")
    html = response.text.lower()

    indicators = {
        "text_math": False,
        "image_math": False,
        "logic_question": False,
    }

    # Check for text-based math questions
    math_patterns = [
        r"what is \d+\s*[\+\-\×\*]\s*\d+",
        r"\d+\s*[\+\-\×\*]\s*\d+\s*=\s*\?",
        r"solve:\s*\d+",
        r"type the (result|answer|sum)",
    ]
    for pattern in math_patterns:
        if re.search(pattern, html):
            indicators["text_math"] = True
            break

    # Check for CAPTCHA images near math-related labels
    captcha_images = soup.find_all("img", attrs={
        "alt": re.compile(r"captcha|math|verify", re.I)
    })
    if captcha_images:
        indicators["image_math"] = True

    # Check for logic questions
    logic_patterns = [
        r"what color is",
        r"how many legs",
        r"what comes next",
        r"is .+ hot or cold",
    ]
    for pattern in logic_patterns:
        if re.search(pattern, html):
            indicators["logic_question"] = True
            break

    return indicators

result = detect_math_captcha("https://example.com/contact")
print(result)

Node.js 检测

const axios = require("axios");
const cheerio = require("cheerio");

async function detectMathCaptcha(url) {
    const { data: html } = await axios.get(url, { timeout: 10000 });
    const $ = cheerio.load(html);
    const lower = html.toLowerCase();

    const indicators = {
        textMath: false,
        imageMath: false,
        logicQuestion: false,
    };

    // Text-based math patterns
    const mathPatterns = [
        /what is \d+\s*[+\-×*]\s*\d+/,
        /\d+\s*[+\-×*]\s*\d+\s*=\s*\?/,
        /solve:\s*\d+/,
        /type the (result|answer|sum)/,
    ];

    for (const pattern of mathPatterns) {
        if (pattern.test(lower)) {
            indicators.textMath = true;
            break;
        }
    }

    // Check for CAPTCHA images
    $("img").each((_, el) => {
        const alt = ($(el).attr("alt") || "").toLowerCase();
        if (/captcha|math|verify/.test(alt)) {
            indicators.imageMath = true;
        }
    });

    return indicators;
}

detectMathCaptcha("https://example.com/contact").then(console.log);

用 OCR 自动解出图片版数学验证码

图片版没法直接用正则解析,得先用 OCR 读出方程式,再靠一张运算符映射表算出答案。下面这个例子调用 CaptchaAI 的图片 OCR 接口:图片转 base64 提交,轮询结果,再用正则拆出运算符和两个操作数。

使用 CaptchaAI 识别图片版数学验证码

import requests
import time
import re

API_KEY = "YOUR_API_KEY"
CAPTCHA_IMAGE_URL = "https://example.com/captcha.png"

# Download the CAPTCHA image
image_data = requests.get(CAPTCHA_IMAGE_URL).content

# Submit to CaptchaAI OCR
import base64
b64_image = base64.b64encode(image_data).decode()

submit = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "base64",
    "body": b64_image,
    "json": 1,
})

task_id = submit.json().get("request")

# Poll for result
for _ in range(30):
    time.sleep(3)
    result = requests.get("https://ocr.captchaai.com/res.php", params={
        "key": API_KEY,
        "action": "get",
        "id": task_id,
        "json": 1,
    })
    data = result.json()
    if data.get("status") == 1:
        ocr_text = data["request"]  # e.g., "7 + 3"
        print(f"OCR result: {ocr_text}")

        # Parse and compute the answer
        match = re.match(r"(\d+)\s*([+\-*/×])\s*(\d+)", ocr_text)
        if match:
            a, op, b = int(match.group(1)), match.group(2), int(match.group(3))
            ops = {"+": a + b, "-": a - b, "*": a * b, "×": a * b, "/": a // b}
            answer = ops.get(op)
            print(f"Answer: {answer}")
        break
    elif "CAPCHA_NOT_READY" in str(data):
        continue

ops 映射表只覆盖了加、减、乘(含全角 ×)、除四种符号——目标站点用了其他写法(比如 ÷),记得补进去,否则 ops.get(op) 会返回 None


常见问题

数学验证码和逻辑验证码是一回事吗?

不完全是。数学验证码考算术——加减乘除;逻辑验证码考常识判断,比如“草是什么颜色”,不需要计算,但需要小型知识库或语言模型才能回答。两者实现都很简单,也都靠固定题库穷举。

为什么现在还有网站在用这么老的验证码?

主要是成本和历史包袱:不用接第三方 API,一段后端代码就能实现,WordPress 插件又把门槛降到几乎为零。很多老系统在 reCAPTCHA、Turnstile 出现前就已上线,之后也没动力替换。

图片版数学验证码要怎么用 API 自动识别?

把图片转成 base64 提交给 OCR 接口,拿到方程式文本后,用正则拆出数字和运算符再计算。CaptchaAI 的图片 OCR 支持 27,500 多种图片验证码格式,数学方程图片是其中一类。

脚本老是提交错误答案,是不是运算符没识别对?

很常见的坑。OCR 经常把 × 认成 x 或星号,如果运算符映射表没覆盖到 OCR 实际吐出来的符号,ops.get(op) 就会返回 None。建议先打印 OCR 原始输出,再核对映射表是否覆盖完整。

想彻底不用数学验证码了,该换成 Turnstile 还是 reCAPTCHA v3?

看你更看重什么。Turnstile 摩擦几乎为零,多数情况下用户完全无感;reCAPTCHA v3 走打分模式,能拿到风险分数,策略上更灵活,但需接入 Google 脚本。


总结

数学和逻辑验证码是最简单的一类挑战,常见于 WordPress 联系表单和没跟上迭代的老系统。纯文本版本可直接从 HTML 用正则解析;图片版本要先过一遍 OCR,再靠四则运算算出答案。批量处理图片版时,用 CaptchaAI 图片 OCR API 提取方程式并求解最省事。虽然对机器人几乎没有防御力,但胜在实现简单、对无障碍访问友好,这类验证码短期内不会消失。

相关文章

该文章已禁用评论。