Use Cases

公共记录搜索自动化的验证码处理

法院案件查不到、地产记录卡在扭曲字母图片上——美国政府门户大多比 reCAPTCHA、Turnstile 出现得还早,用的还是图片验证码和数学题,正是 OCR 最擅长的场景。

下面用 Python 和 JavaScript 讲清楚怎么接入。

政府门户常见的验证码类型

门户类型 常见验证码 挑战示例
法院案件搜索 自定义文本验证码 5–6 位扭曲字母数字
县级地产记录 数学验证码 “4 + 7 等于多少?”
工商实体查询 图片文字验证码 扭曲字母 + 线条噪音
重要记录查询 reCAPTCHA v2 图像网格选择
建筑许可查询 简单文本验证码 4 位数字代码
UCC 备案查询 自定义 OCR 验证码 大小写混合 + 背景噪音

国内站点早普及了 GeeTest(极验)滑块,美国政府门户却还停留在算术题、扭曲字符这一代——后端多是遗留系统,升级慢。

做跨境尽调、核对美国备案信息的团队会经常碰到。

Python 实战:识别法院网站验证码并提交查询

PublicRecordsSearcher 类:加载搜索页 → 提取验证码图片 → 提交给 CaptchaAI 识别 → 带结果重新提交表单。

换门户通常只需调整 _extract_captcha_url 的选择器。

import requests
import base64
import time
from urllib.parse import urljoin

class PublicRecordsSearcher:
    def __init__(self, api_key):
        self.api_key = api_key
        self.session = requests.Session()
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        })

    def search_court_records(self, portal_url, case_number):
        """Search court records, solving image CAPTCHAs as needed."""
        # Load the search page
        page = self.session.get(f"{portal_url}/search")

        # Extract CAPTCHA image
        captcha_img_url = self._extract_captcha_url(page.text, portal_url)
        if not captcha_img_url:
            # No CAPTCHA on this page
            return self._submit_search(portal_url, case_number)

        # Download and solve CAPTCHA
        img_response = self.session.get(captcha_img_url)
        captcha_text = self._solve_image_captcha(img_response.content)

        # Submit search with solved CAPTCHA
        return self._submit_search(portal_url, case_number, captcha_text)

    def _extract_captcha_url(self, html, base_url):
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(html, "html.parser")

        # Look for common CAPTCHA image patterns
        captcha_img = (
            soup.find("img", {"id": "captchaImage"}) or
            soup.find("img", {"class": "captcha"}) or
            soup.find("img", attrs={"src": lambda s: s and "captcha" in s.lower()})
        )

        if captcha_img and captcha_img.get("src"):
            return urljoin(base_url, captcha_img["src"])
        return None

    def _solve_image_captcha(self, image_bytes):
        img_base64 = base64.b64encode(image_bytes).decode("utf-8")

        resp = requests.post("https://ocr.captchaai.com/in.php", data={
            "key": self.api_key,
            "method": "base64",
            "body": img_base64,
            "json": 1
        })
        task_id = resp.json()["request"]

        for _ in range(30):
            time.sleep(3)
            result = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": self.api_key,
                "action": "get",
                "id": task_id,
                "json": 1
            })
            data = result.json()
            if data["status"] == 1:
                return data["request"]

        raise TimeoutError("CAPTCHA solve timed out")

    def _submit_search(self, portal_url, case_number, captcha_text=None):
        form_data = {"caseNumber": case_number}
        if captcha_text:
            form_data["captcha"] = captcha_text

        response = self.session.post(
            f"{portal_url}/search/results",
            data=form_data
        )
        return response.text

# Usage
searcher = PublicRecordsSearcher("YOUR_API_KEY")
results = searcher.search_court_records(
    "https://courts.example.gov",
    "2024-CV-12345"
)

常用请求参数

_solve_image_captcha 用到的关键参数:

参数 取值 使用场景
method base64 验证码图片以字节形式下载
method post 直接提交图片文件
language 0 英文 / 拉丁字母验证码
numeric 1 纯数字验证码
min_len / max_len 视情况而定 字符数量可预测时使用
textinstructions 自定义提示词 数学验证码或特定格式

数学验证码怎么处理

县级地产记录系统常用“4 + 7 等于多少”这类算术题代替文字验证码,CaptchaAI 把它当文本识别处理,用 textinstructions 告诉它“只返回数字”即可:

def solve_math_captcha(self, image_bytes):
    """Solve math CAPTCHAs like '4 + 7 = ?'"""
    img_base64 = base64.b64encode(image_bytes).decode("utf-8")

    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": self.api_key,
        "method": "base64",
        "body": img_base64,
        "textinstructions": "solve the math equation and return only the number",
        "json": 1
    })
    task_id = resp.json()["request"]

    # Poll for result
    for _ in range(30):
        time.sleep(3)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": self.api_key,
            "action": "get",
            "id": task_id,
            "json": 1
        })
        data = result.json()
        if data["status"] == 1:
            return data["request"]

    raise TimeoutError("Math CAPTCHA solve timed out")

JavaScript 版本:批量查询多个政府门户

要同时核对一家公司的州工商登记和县法院案件,RecordsAggregator 会依次查询多个门户、调用 CaptchaAI 识别验证码,把结果汇总成数组,单个门户出错不影响其余查询:

class RecordsAggregator {
  constructor(apiKey) {
    this.apiKey = apiKey;
  }

  async searchAcrossPortals(query, portals) {
    const results = [];

    for (const portal of portals) {
      try {
        const data = await this.searchPortal(portal, query);
        results.push({ portal: portal.name, records: data });
      } catch (error) {
        results.push({ portal: portal.name, error: error.message });
      }
    }

    return results;
  }

  async searchPortal(portal, query) {
    const pageResponse = await fetch(portal.searchUrl);
    const html = await pageResponse.text();

    // Check for image CAPTCHA
    const captchaMatch = html.match(/captcha[^"]*\.(?:png|jpg|gif)/i);
    let captchaAnswer = null;

    if (captchaMatch) {
      const imgUrl = new URL(captchaMatch[0], portal.searchUrl).href;
      const imgData = await fetch(imgUrl);
      const buffer = await imgData.arrayBuffer();
      const base64 = Buffer.from(buffer).toString('base64');

      captchaAnswer = await this.solveImageCaptcha(base64);
    }

    // Submit search
    const formData = new URLSearchParams({ q: query });
    if (captchaAnswer) formData.append('captcha', captchaAnswer);

    const response = await fetch(portal.searchUrl, {
      method: 'POST',
      body: formData
    });

    return response.text();
  }

  async solveImageCaptcha(base64Image) {
    const submitResp = await fetch('https://ocr.captchaai.com/in.php', {
      method: 'POST',
      body: new URLSearchParams({
        key: this.apiKey,
        method: 'base64',
        body: base64Image,
        json: '1'
      })
    });

    const { request: taskId } = await submitResp.json();

    for (let i = 0; i < 30; i++) {
      await new Promise(r => setTimeout(r, 3000));
      const result = await fetch(
        `https://ocr.captchaai.com/res.php?key=${this.apiKey}&action=get&id=${taskId}&json=1`
      );
      const data = await result.json();
      if (data.status === 1) return data.request;
    }

    throw new Error('CAPTCHA solve timed out');
  }
}

// Usage
const aggregator = new RecordsAggregator('YOUR_API_KEY');
const results = await aggregator.searchAcrossPortals('Smith LLC', [
  { name: 'State Business Registry', searchUrl: 'https://sos.example.gov/search' },
  { name: 'County Court Records', searchUrl: 'https://courts.example.gov/search' }
]);

常见故障排查

问题 原因 处理方式
验证码图片返回 403 session cookie 丢失 先加载搜索页再请求图片
识别结果不正确 图片质量太差 图像预处理指南提高对比度、去噪
提交时验证码又变了 表单 token 已过期 与验证码图片一起重新提取隐藏字段
识别通过后结果为空 POST 跳转丢失 cookie allow_redirects=True 并保持同一 session

常见问题

政府门户网站为什么还在用这种老式图片验证码?

政府系统的后端比 reCAPTCHA、Turnstile 出现得还早,图片和算术题验证码是当年的行业标准,升级周期以年计。

CaptchaAI 能识别数学验证码和自定义 OCR 验证码吗?

能。CaptchaAI 支持超过 27,500 种图片验证码类型,数学题、扭曲字母、纯数字都归图片 / OCR 识别,走同一个 in.php / res.php 接口,用 textinstructions 说明解析方式即可。

批量查询多个政府门户会不会被限流?

会有风险,但这是门户自身的策略,和识别无关。

加请求间隔、控制并发、复用同一 session 更稳。

下一步

打通验证码识别流程后,接入现有查询脚本即可。获取你的 CaptchaAI API Key,开始批量处理政府门户验证码。


后续阅读

该文章已禁用评论。