法院案件查不到、地产记录卡在扭曲字母图片上——美国政府门户大多比 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,开始批量处理政府门户验证码。