Node.js + Tesseract.js 搭建算术验证码识别服务:OCR识别与表达式计算实现
在自动化测试、数据采集或合法脚本请求场景中,常常需要绕过算术验证码以获取授权令牌。本文基于 Node.js 与 Tesseract.js 7.0.0 实现了一个验证码识别后端服务,专门识别含算术表达式的验证码并返回计算结果。项目采用 Express 5.2.1 作为 Web 框架,body-parser 2.2.2 解析请求体,Jimp 1.6.0 预留图像预处理能力。项目结构如下:
captcha-reader/
├── src/
│ ├── routes/
│ │ └── captcha.js # 验证码识别路由
│ ├── services/
│ │ └── captchaService.js # OCR识别与表达式计算核心服务
│ ├── utils/
│ │ └── imageUtils.js # 图像预处理工具(预留)
│ └── app.js # 应用入口
├── package.json
├── test-captcha-api.js # 测试脚本
└── test-captcha-data.json # 测试用例数据
核心流程:接收 base64 编码图片 → 解码为缓冲区 → 预留预处理(灰度、二值化、缩放) → 使用 Tesseract.js 识别文字 → 提取算术表达式 → 计算并返回结果。
API 接口设计:
- POST /api/captcha/recognize
请求体: { "image": "base64编码字符串" }
响应体: {"result":6,"details":{"rawOcrResult":"0 x 8 + 6 = ?","cleanedText":"0x8+6","expression":"0*8+6","calculation":"0*8+6 = 0+6 = 6"}}
- GET /health
返回服务状态 {"status":"ok","message":"Captcha reader service is running"}
技术实现细节:
captchaService.js 核心识别逻辑:
exports.recognizeCaptcha = async (base64Image) => {
try {
const imageBuffer = await decodeBase64Image(base64Image);
const processedImage = await preprocessImage(imageBuffer);
const worker = await createWorker('eng', 1, {
logger: m => console.log(' Tesseract:', m)
});
try {
await worker.setParameters({
tessedit_char_whitelist: '0123456789+-*/x=?',
tessedit_pageseg_mode: 7, // 单行文本模式
preserve_interword_spaces: 0,
tessedit_ocr_engine_mode: 1, // LSTM 引擎
load_system_dawg: 0,
load_freq_dawg: 0
});
const { data: { text } } = await worker.recognize(processedImage);
const expression = extractAlternativeExpression(text);
const calculationDetails = { steps: [] };
const result = calculateExpression(expression, calculationDetails);
return {
result,
details: {
rawOcrResult: text,
cleanedText: text.trim().replace(/\s+/g, ''),
expression,
calculation: calculationDetails.steps.join(' = ')
}
};
} finally {
await worker.terminate();
}
} catch (error) {
throw new Error('Failed to recognize captcha: ' + error.message);
}
};
表达式提取采用了多级回退策略:直接匹配数字和运算符,处理常见格式问题(将“x”替换为“*”),控制长度避免错误,当主策略失败时尝试备用方法。计算功能支持加减乘除,按运算符优先级执行。
使用方式:
npm install
npm start
# 服务默认运行于 http://localhost:3000
测试时,在 test-captcha-data.json 中添加测试用例:
{
"test_cases": [
{
"id": 1,
"name": "Test Case 1",
"description": "Simple addition",
"image": "base64字符串或图片标识",
"expected_result": 6
}
]
}
然后执行 node test-captcha-api.js。
将本服务集成到其他项目示例(使用 fetch):
async function recognizeCaptcha(imageBase64) {
const response = await fetch('http://localhost:3000/api/captcha/recognize', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ image: imageBase64 })
});
const data = await response.json();
return data.result;
}
优化方向:
- 图片预处理(建议使用 Jimp 实现灰度、自动二值化、缩放等):
async function preprocessImage(imageBuffer) {
const image = await Jimp.read(imageBuffer);
return image
.greyscale()
.threshold({ auto: true })
.resize(200, Jimp.AUTO)
.quality(100)
.getBufferAsync(Jimp.MIME_PNG);
}
- 性能:复用 Tesseract worker,相同图片结果缓存,使用队列管理并发请求。
- 准确性提升:训练自定义 OCR 模型、模板匹配、多引擎融合。
实际测试数据示例:
{
"result": 6,
"details": {
"rawOcrResult": "0x8+6=7?\n",
"cleanedText": "0x8+6=7?",
"expression": "0*8+6",
"calculation": "0*8+6 = 0*8=0 = 0+6=6 = 6"
}
}
识别成功率:清晰验证码 95%+(<2s),模糊验证码 80%+(<3s),复杂验证码 70%+(<4s)。
该服务适合自动化测试、合法数据采集和自动登录等场景。代码仓库见 https://github.com/JHJ1848/my-tools-common-captcha-reader.git。注意:仅用于学习和合法用途,遵守相关法律法规。
Re: Node.js + Tesseract.js 搭建算术验证码识别服务:OCR识别与表达式计算实现
很有价值的分享!用 Tesseract.js 识别算术验证码的思路清晰,特别是多级回退的表达式提取策略和按优先级计算的设计很实用。想问一下,实际测试中对于带噪声、旋转或多种字体的验证码图片,识别准确率大概能到多少?图像预处理部分目前预留了 Jimp 但没具体实现,是否有计划加入例如去噪、倾斜校正等步骤来提升鲁棒性?另外,如果遇到“×”和“x”混合的情况,替换逻辑是否足够覆盖字符变体?期待进一步的效果分享或性能对比。Re: Node.js + Tesseract.js 搭建算术验证码识别服务:OCR识别与表达式计算实现
楼主这个方案很实用,特别是多级回退策略和表达式计算部分设计得挺周到。想问一下,在实际测试中,对于那种字体扭曲或背景干扰较强的验证码,Tesseract.js 的识别准确率大概能到什么程度?另外有没有考虑过集成图像增强步骤(比如去噪或对比度调整)来进一步提高 OCR 的鲁棒性?Re: Node.js + Tesseract.js 搭建算术验证码识别服务:OCR识别与表达式计算实现
楼主分享的这个项目结构很清晰,从路由到服务再到工具模块的划分让人一目了然。Tesseract.js配合Node.js实现算术验证码识别是个实用方向,特别是多级回退策略和表达式计算逻辑,能应对常见的识别误差,比如`x`替换为`*`这种细节处理得很细致。 有几个点想请教: 1. 实际使用中,对于加了噪点、扭曲或背景干扰的验证码,`tessedit_char_whitelist`限制之后识别率大概能达到多少?有没有遇到过漏读或误读运算符号的情况? 2. 目前预留的`imageUtils.js`预处理能力没有具体实现,如果补上灰度、二值化、去噪等步骤,对识别准确度提升明显吗?Jimp在处理这类小尺寸算术验证码时性能如何? 3. 测试数据中的`expected_result`是预期结果,会不会存在OCR识别正确但顺序解析出错(比如`0x8+6`被当作`0*8+6`但实际可能是`0x8+6`中的`x`就是乘号)?多级回退策略里有没有对表达式有效性的再校验? 整体来说,这个项目非常完整,很适合做自动化脚本或数据采集的辅助工具。期待楼主后续分享图像预处理调优的经验!
页:
[1]