俄语、乌克兰语、保加利亚语和塞尔维亚语网站使用西里尔文文本验证码,这些验证码看起来与拉丁文非常相似,例如“Д、“Д、“С”、“Е”、“Д、“О”等字符与拉丁文对应字符看起来相同,但 Unicode 代码点完全不同。这造成了标准拉丁文 OCR 所忽略的独特识别和提交挑战。
西里尔字母与拉丁字母易混淆字符
| 看起来像 | 拉丁 | 西里尔 | 统一码 |
|---|---|---|---|
| 一个 | 一个 (U+0041) | А (U+0410) | 不同的代码点 |
| 乙 | 乙 (U+0042) | В (U+0412) | 西里尔字母是“Ve” |
| C | C (U+0043) | С (U+0421) | 西里尔字母是“Es” |
| 乙 | E (U+0045) | Е (U+0415) | 编码不同 |
| H | H (U+0048) | Н (U+041D) | 西里尔字母是“En” |
| 氧 | 欧 (U+004F) | Ðz (U+041E) | 不同的代码点 |
| 磷 | P (U+0050) | Ð (U+0420) | 西里尔字母是“Er” |
提交错误的代码点会导致表单验证拒绝外观正确的文本。
Python:西里尔文字图像验证码
import requests
import base64
import time
API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
def solve_cyrillic_captcha(image_path: str) -> str:
"""Solve a Cyrillic text image CAPTCHA."""
with open(image_path, "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
resp = requests.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "base64",
"body": image_b64,
"language": 2, # Non-Latin character support
"json": 1,
}, timeout=30).json()
if resp.get("status") != 1:
raise RuntimeError(f"Submit: {resp.get('request')}")
task_id = resp["request"]
for _ in range(24):
time.sleep(5)
poll = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}, timeout=15).json()
if poll.get("request") == "CAPCHA_NOT_READY":
continue
if poll.get("status") == 1:
return poll["request"]
raise RuntimeError(f"Solve: {poll.get('request')}")
raise RuntimeError("Timeout")
def solve_cyrillic_from_session(session: requests.Session,
captcha_url: str) -> str:
"""Solve a Cyrillic CAPTCHA within a session context."""
resp = session.get(captcha_url, timeout=15)
image_b64 = base64.b64encode(resp.content).decode()
submit = requests.post(SUBMIT_URL, data={
"key": API_KEY,
"method": "base64",
"body": image_b64,
"language": 2,
"json": 1,
}, timeout=30).json()
if submit.get("status") != 1:
raise RuntimeError(f"Submit: {submit.get('request')}")
task_id = submit["request"]
for _ in range(24):
time.sleep(5)
poll = requests.get(RESULT_URL, params={
"key": API_KEY, "action": "get", "id": task_id, "json": 1,
}, timeout=15).json()
if poll.get("request") == "CAPCHA_NOT_READY":
continue
if poll.get("status") == 1:
return poll["request"]
raise RuntimeError(f"Solve: {poll.get('request')}")
raise RuntimeError("Timeout")
def verify_cyrillic(text: str) -> bool:
"""Verify that solved text contains Cyrillic characters."""
return any('\u0400' <= ch <= '\u04FF' for ch in text)
# --- Russian website form flow ---
def solve_russian_form(form_url: str, captcha_url: str,
form_data: dict) -> requests.Response:
"""Complete a Russian website form with CAPTCHA."""
session = requests.Session()
session.headers.update({
"Accept-Language": "ru-RU,ru;q=0.9",
})
# Establish session
session.get(form_url, timeout=15)
# Solve CAPTCHA
captcha_text = solve_cyrillic_from_session(session, captcha_url)
print(f"Cyrillic CAPTCHA: {captcha_text}")
if verify_cyrillic(captcha_text):
print("Confirmed: contains Cyrillic characters")
form_data["captcha"] = captcha_text
return session.post(form_url, data=form_data, timeout=30)
# --- Usage ---
text = solve_cyrillic_captcha("russian_captcha.png")
print(f"Solved: {text}")
print(f"Is Cyrillic: {verify_cyrillic(text)}")
print(f"Unicode codepoints: {[hex(ord(c)) for c in text]}")
JavaScript:西里尔验证码处理
const API_KEY = "YOUR_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
const fs = require("fs");
async function solveCyrillicCaptcha(imagePath) {
const imageB64 = fs.readFileSync(imagePath, "base64");
const body = new URLSearchParams({
key: API_KEY,
method: "base64",
body: imageB64,
language: "2",
json: "1",
});
const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);
const taskId = resp.request;
for (let i = 0; i < 24; i++) {
await new Promise((r) => setTimeout(r, 5000));
const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
const poll = await (await fetch(url)).json();
if (poll.request === "CAPCHA_NOT_READY") continue;
if (poll.status === 1) return poll.request;
throw new Error(`Solve: ${poll.request}`);
}
throw new Error("Timeout");
}
function isCyrillic(text) {
return /[\u0400-\u04FF]/.test(text);
}
function showCodepoints(text) {
return [...text].map((ch) => `${ch}=U+${ch.codePointAt(0).toString(16).padStart(4, "0")}`);
}
// Usage
const text = await solveCyrillicCaptcha("russian_captcha.png");
console.log(`Solved: ${text}`);
console.log(`Is Cyrillic: ${isCyrillic(text)}`);
console.log(`Codepoints: ${showCodepoints(text).join(", ")}`);
常见的西里尔验证码模式
| 图案 | 描述 | 例子 |
|---|---|---|
| 纯西里尔文字 | 随机俄语单词 | ” “ |
| 混合拉丁文 + 西里尔文 | 两个脚本都在一张图像中 | ABСDе(A,B,D 拉丁语;С,е 西里尔语) |
| 拼写出的西里尔字母数字 | 字数 | ПÐ́ÐðÐ(五)、ÐðРÐ(三) |
| 俄语数学 | 文字中的算术 | два п |
| 扭曲的西里尔字母 | 俄语文本扭曲 | 西里尔字母的标准 OCR 挑战 |
故障排除
| 问题 | 原因 | 处理方式 |
|---|---|---|
| 表单拒绝看起来正确的文本 | 拉丁语/Cyrillic 同形字不匹配 | 检查 Unicode 代码点 – А (U+0410) – A (U+0041) |
| 显示乱码 | 编码错误 | 全程使用 UTF-8;设置 response.encoding = 'utf-8' |
| 混合脚本文本部分错误 | OCR 混淆拉丁文和西里尔文 | CaptchaAI 与 language=2 正确区分 |
| 缺少乌克兰语特定字符 | ґ、є、і、ї 无法识别 | 这些由 language=2 支持 |
| 验证码区分大小写 | 大写 /lowercase 很重要 | 完全按照 CaptchaAI 返回的内容提交 |
常问问题
CaptchaAI 如何区分西里尔字母 В 和拉丁字母 B?
CaptchaAI 的 OCR 模型经过上下文和字形特征的训练。当设置 language=2 时,求解器使用西里尔字母识别模型返回正确的 Unicode 代码点。返回的文本将使用西里尔字符 (U+0400–U+04FF) 表示俄语文本。
它可以处理乌克兰语特定字符吗?
是的。乌克兰语使用俄语中不存在的字符 - ґ (U+0491)、є (U+0454)、і (U+0456)、ї (U+0457)。 CaptchaAI 通过 language=2 识别这些。该求解器可以处理所有西里尔文字,包括俄语、乌克兰语、保加利亚语和塞尔维亚语。
如果验证码混合了西里尔字母和拉丁字母怎么办?
一些验证码故意混合脚本以造成歧义。 CaptchaAI 返回每个字符具有正确 Unicode 代码点的文本。使用 verify_cyrillic() 函数或通过检查代码点进行验证。
下一步
解决俄语和斯拉夫网站上的西里尔验证码 -”获取您的 CaptchaAI API 密钥。
相关指南:
- 解决中文网站上的验证码
- 多语言图像验证码字符集
- 验证码本地化和语言设置