☰
开源验证码识别Web API:覆盖OCR、滑块、点选、旋转等类型
2026/10/19 5:38:20 网站建设 项目流程

做自动化采集和数据同步的朋友,十有八九绕不开验证码这道坎。早期我处理验证码的方式挺笨的,要么手动输入,要么针对每一套验证码单独写死一段识别脚本,时间全浪费在重复造轮子上。后来我把手头的识别能力统一收敛成一个Web API服务,也就是今天要分享的AntiCAP-WebApi——它把OCR、滑块、点选、旋转等几十种常见验证码识别方式整合到一套HTTP接口里,调用方只需要按约定格式提交图片,就能拿到结构化结果。

这个项目我在实际生产中跑了小半年,从最初只能处理纯数字验证码,到后面陆续接入了缺口滑块、汉字点选、图片旋转、计算题等类型,中途踩了不少坑,也反复重构过几版。现在源码和打包好的成品一起放出来,如果你正在做自动化测试、数据采集、批量注册脚本,或者单纯想研究验证码侧的技术对抗思路,这份代码应该能帮你省下大量调研时间。下面我从设计思路、源码结构、部署调用到排查经验完整过一遍。

1. 项目概述:这个验证码识别服务到底能做什么

1.1 项目能解决什么问题

AntiCAP-WebApi解决的核心痛点,是把“验证码识别”从一段零散的本地脚本升级为独立、可复用的HTTP服务。以前每次遇到新验证码,我都要重新打开一个Python脚本,加载模型、处理图片、打印结果,然后手动把结果填回目标系统。验证码需求一多,本地环境就乱成一锅粥,模型版本、依赖库互相打架。

现在整个识别能力以WebApi形态独立部署,任何语言写的程序只要会发HTTP请求,就能够使用识别能力。团队里其他人不需要装Python环境,不需要理解识别算法细节,只需要知道“提交什么格式的图片,能拿回什么格式的结果”。这种解耦让项目边界非常清晰,识别服务本身演进迭代,业务端完全不受影响。对个人开发者来说,部署一次之后,所有脚本和自动化流程都可以通过接口复用这套能力,边际成本趋近于零。

核心功能点可以概括成三块:

  • 多类型识别:支持OCR文本、滑块缺口、点选坐标、旋转角度、计算题等主流验证码形态。
  • 统一API格式:无论哪种验证码,都通过同一个识别接口提交,返回JSON结构化结果。
  • 独立部署:以Web服务方式运行,不依赖任何IDE或图形界面,适合放服务器上跑。

1.2 适用人群与典型场景

我在分享这个项目时,最容易引起共鸣的有三类人。第一类是做数据采集的开发者,需要登录目标站点抓取数据,结果在登录页被验证码卡住,手动输入一次两次还好,规模化采集时人工成本完全扛不住。第二类是自动化测试工程师,做Web端回归测试时,流程跑到验证码环节就断掉,只能写死验证码或者绕过,测试覆盖率一直提不上去。第三类是刚开始研究验证码识别技术的同学,想知道一套完整的识别服务应该怎么组织,从模型选择到接口封装有哪些门道。

典型场景我用几个实际例子说明:

场景A:某数据采集脚本每天早上需要登录一次后台导出报表,登录页有滑块验证码。以前脚本只能卡住等人工处理,接入AntiCAP-WebApi之后,脚本先请求识别接口拿缺口坐标,再驱动浏览器拖拽,全程无人值守。

场景B:自动化测试框架中新增了“注册流程”用例,注册页有点选验证码。测试脚本调用识别接口拿到点击坐标列表,逐个模拟点击,整个流程从手工验证变成全自动。

场景C:个人开发者维护着几个签到脚本,验证码类型各不相同。统一接入这个服务后,新增脚本只需要处理HTTP返回结果,不需要关心验证码识别过程。

2. 支持的验证码类型全知道

很多人一听到“验证码识别”就以为只是图片上的几个字符转成文本,其实验证码形态已经演变得非常丰富了。AntiCAP-WebApi支持的几十种验证码,按交互方式可以分成四个大类,每一类背后的识别技术路线完全不同。

2.1 OCR文本类验证码识别

这类是最经典的形态,纯文本验证码,包括四位数字、字母数字混合、带干扰线的字符、扭曲变形的单词、算术表达式等。识别这一类验证码,核心是端到端的OCR能力。

我在实现时走的是“图像预处理 + OCR引擎 + 后处理纠错”路线。图像预处理阶段,用OpenCV把彩色图片转灰度、二值化、去噪点、去除干扰线;OCR引擎负责把处理后的图片上的字符切片转换成文本;后处理阶段针对常见验证码做规则纠错,比如剔除容易混淆的字符(字母O和数字0、字母I和数字1),或者验证算术表达式的结果。

需要说明的是,不同OCR引擎的适用场景差异很大。基于模板匹配的传统OCR只能处理规整字体,对扭曲变形的验证码几乎无效;基于深度学习训练的OCR模型抗干扰能力强,但需要准备大量标注样本。这个项目默认整合了一个预训练OCR模型和一套可插拔的引擎接口,方便你根据目标验证码形态替换或微调。

2.2 滑块验证码识别

滑块验证码是目前Web端最常见的形态,表现形式有两种:一种是缺口滑块,用户需要把滑块拖动到背景图的缺口位置;另一种是拼图滑块,需要把拼图块拖到正确位置。

滑块识别的技术难点在于定位缺口坐标,而不是拖拽本身。实现思路是:先通过图像处理提取背景图中的缺口位置,再计算出滑块需要移动的距离。我在源码中使用的是边缘检测与轮廓分析相结合的方法,先Canny边缘检测获取轮廓信息,再通过形态学处理突出缺口区域,最后计算出缺口中心点坐标。

这块的兼容性需要特别说明,不同站点的滑块图片规格、缺口样式千差万别。有的带阴影,有的是透明拼图,有的缺口周围有复杂纹理。所以源码里提供了校准参数配置,你可以针对特定站点微调检测灵敏度、边缘阈值等参数。实测数据是:规范缺口样式的识别准确率在95%以上,特殊样式经过参数调整后也能达到可用水平。

2.3 点选验证码识别

点选验证码在移动端和部分高安全等级站点上很常见。表现形式有两种:一种是文字点选,系统给出文字提示比如“点击下图中的汽车”,用户需要点击图片中对应的物体;另一种是图片点选,直接展示一组图片,按要求点击某几张。

点选验证码的识别链路比滑块复杂,因为既要做目标检测(找到候选区域),又要做语义匹配(判断点击哪个区域)。项目实现时用了两步走:第一步通过目标检测网络框出图片中所有候选目标及坐标;第二步提取每个目标的特征,与题目文字进行语义匹配,最终返回需要点击的坐标列表。

这类验证码的准确率受训练数据影响很大,公开数据集和站点实际数据存在分布差异。我在部署后通常建议团队先小批量收集目标站点的真实图片,对检测模型做数据增强或增量训练。

2.4 旋转及其他验证码识别

旋转验证码通常是一张角度偏移的图片,用户需要把它旋转到正位。识别这类验证码的技术思路与滑块完全不同,滑块是二维空间定位,旋转是一维角度回归。

实现上我试过多种方案:第一种是直接用CNN分类模型,把角度离散化成360个类别;第二种是目标检测配合主方向分析,先检测出图片中物体的主轴,再计算需要旋转的角度;第三种是图像匹配方案,将待旋转图片与正位模板做相似度比对。实测下来,CNN回归方案稳定性最好,角度误差控制在5度以内的概率约90%。

除了以上几大类型,项目还集成了其他交互式验证码的识别入口,比如顺序点击类、宫格拼图类等。这些形态的识别思路是组合前面提到的技术——目标检测找候选区域,OCR或语义模型排顺序,最后生成点击序列。

2.5 验证码类型与识别方案对照表

我用一张表总结一下目前主流验证码类型和对应的识别方案,方便你快速判断项目能否覆盖目标场景。

验证码大类常见具体形式核心技术方案返回结果类型
OCR文本类纯数字、字母混合、算术题、单词图像预处理 + OCR模型 + 规则纠错文本字符串
滑块类缺口滑块、拼图滑块、无缝滑块OpenCV边缘检测 + 轮廓分析目标横坐标、移动距离
点选类文字点选、图片点选、图标点选目标检测 + 语义匹配或特征匹配坐标列表
旋转类旋图校正、方向错位图CNN角度回归旋转角度
组合类顺序点击、宫格拼图、滑动拼图多种方案的策略组合坐标序列或步骤列表

3. 系统架构与设计思路

单看识别算法再强,如果没有一个好的服务框架把能力组织起来,实战中还是会手忙脚乱。这一章节我详细说明项目的系统架构,以及每个设计决策背后的考虑。

3.1 总体架构分层

AntiCAP-WebApi整体上分为四层:接入层、路由调度层、识别引擎层、结果处理层。

接入层就是HTTP服务本身,负责接收请求、解析参数、校验图片格式、做鉴权控制。这一层我把接口协议定义得尽量简单,所有识别统一走一个入口,通过type参数区分验证码类型。

路由调度层是识别服务的“大脑”,根据type参数把请求分发到对应的识别引擎。调度层还承担着引擎降级和超时控制的责任,当某个引擎识别超时或异常时,能快速返回错误码,避免业务端长时间等待。

识别引擎层是核心,每种验证码类型对应一个独立引擎,互相解耦。引擎内部包含图像预处理、特征提取、模型推理、后处理纠错几个环节,每个环节都抽象出独立模块,方便替换升级。

结果处理层负责把引擎的原始输出标准化,统一成约定好的JSON响应结构,同时记录识别耗时、置信度等元信息,方便调用方做质量监控。

3.2 技术选型背后的取舍

后端语言框架我选了Python加FastAPI。选Python是因为验证码识别生态里深度学习框架、OpenCV图像处理库都是Python最顺手;FastAPI相比Flask更现代,自带接口文档和数据校验,请求处理性能也不错。如果你更熟悉Java或Node,照着重写一版也不难,核心算法和设计思路都是语言无关的。

模型推理这块,训练阶段我用的深度学习框架是PyTorch,部署阶段用ONNX Runtime加载模型。为什么要做这种拆分?因为PyTorch的推理效率在CPU场景下不够理想,ONNX Runtime做了大量算子优化,CPU推理速度能提升两到三倍,而且不需要在部署环境里安装庞大的训练依赖库。另外ONNX Runtime支持GPU加速,如果服务器有显卡,可以无缝切到CUDA执行。

图像处理这块统一用OpenCV,没有太多悬念。选择它一方面是因为接口丰富,边缘检测、形态学操作、图像变换都是一行调用;另一方面是Python和C++版本可以替换,真到性能瓶颈时可以拿C++重写识别热路径。

3.3 识别流程与数据流

一次完整的识别请求,内部数据流是这样的:客户端把图片以Base64字符串或其他格式POST到接口,接入层解码还原为图像数组,同时解析出验证码类型type和附加参数;路由调度层根据type找到对应引擎,把图像传给引擎;引擎内部先做预处理,再做特征提取或模型推理,最后输出原始结果;结果处理层对原始结果做规则纠错,组装JSON响应,返回给客户端。

这里有一个细节值得展开:为什么入参用Base64而不是multipart文件上传?实际使用中我发现,很多自动化脚本拿到验证码图片时已经是内存中的二进制内容,Base64传输意味着调用方不需要先把图片写盘再上传,少了一次不必要的磁盘IO。同时Base64字符串可以放心地走JSON协议,对调用方来说更省事。

另一处关键设计是超时降级。识别任务中模型推理耗时有波动,高峰期可能出现排队。我给识别引擎加了异步任务队列,同时提供同步和异步两种调用模式:同步模式适合单张识别、对响应时间不敏感的场景;异步模式适合批量识别场景,提交任务后轮询取结果,能显著提升吞吐量。

4. 核心源码模块解读

聊完了架构,接下来进入源码层面。这一章不会逐行贴代码(源码和成品一起放出来了,篇幅有限),但会把项目目录结构、核心接口协议、关键算法实现思路过一遍,确保你拿到代码后知道从哪看起、去哪改。

4.1 项目目录结构与代码组织

拿到项目后,建议先看目录结构,整体比较清晰:

  • main.py:FastAPI应用入口,路由定义、启动逻辑都在这里。
  • api/:接口层代码,处理请求解析和响应包装。
  • engine/:识别引擎层,每种验证码类型一个子模块。
  • common/:公共工具库,封装图像处理、日志、配置读取等基础能力。
  • models/:存放预训练模型文件或模型下载说明。
  • tests/:单元测试和接口联调用例。
  • config/:配置文件目录,引擎参数、服务器参数都集中管理。

我的经验是,拿到代码先跑通hello world,再根据自己的目标验证码类型去看对应引擎。不要一开始陷入算法细节,确认接口能通、返回结果正确之后,再逐步深入也不迟。

4.2 统一请求与响应设计

接口协议是整个项目最值得借鉴的设计之一。统一识别接口的请求结构是这样的:

{ "type": "slider", "images": { "background": "BASE64字符串", "piece": "BASE64字符串" }, "ext_params": { "background_width": 300, "background_height": 150 } }

识别结果响应结构:

{ "code": 0, "msg": "success", "data": { "target_x": 162, "target_y": 36, "distance": 118, "confidence": 0.97 }, "cost_ms": 240 }

我设计协议时坚持了两个原则。第一个是“所有类型共用一套结构”,type字段区分类型,images字段是图片映射,ext_params放附加参数,data字段统一放结果,具体字段随type变化。这样调用方不用为每一种验证码单独写一套对接逻辑。第二个是“明确返回置信度”,很多脚本在自动处理失败时需要知道结果可不可靠,如果置信度低可以选择重试而不是盲目提交。

4.3 滑块缺口识别实现思路

滑块验证码引擎里最核心的是缺口定位算法,我在实现时走的是OpenCV边缘检测路线。先读取背景图,转灰度,做高斯模糊去除噪声,然后Canny边缘检测提取边缘信息,再用形态学闭运算把缺口区域连接成完整轮廓,最后遍历轮廓找最大连通区域,计算其中心点作为缺口位置。

这里有个关键点要提醒:Canny边缘检测的两个阈值参数对结果影响非常大。阈值设高了,缺口边缘提取不全,可能找不到目标;阈值设低了,背景纹理被误检成缺口,定位偏移严重。我采用的方法是动态计算阈值,先统计图像梯度均值,再按均值的倍数设定高低阈值,实测比固定阈值鲁棒得多。

另一种常见的缺口定位方案是模板匹配,就是拿拼图块直接在背景图上滑动找最佳匹配位置。模板匹配对同一站点固定风格图片效果更好,但跨站点适配能力差。项目里我把边缘检测和模板匹配都实现了,默认走边缘检测,config里可以切换方式。

4.4 OCR与模型推理模块

OCR引擎的实现是“集成多种方案 + 统一接口”。核心抽象是OcrEngine基类,定义了recognize方法,接收图像数组返回字符串。不同的OCR实现方式通过继承这个基类来扩展。

目前内置的OCR方案有三类:轻量级的传统OCR引擎、预训练深度学习OCR模型、基于规则的字符分割识别器。实际调用时,路由调度层根据type判断选用哪个方案,也可以配置策略模式——先用深度学习模型,置信度低时降级用传统引擎做二次确认。

模型推理模块统一封装在common/inference.py里。初始化时加载ONNX Runtime的InferenceSession,推理时输入归一化后的图像张量,输出识别置信度向量。我建议你重点关注这个模块,如果后续要换自己的模型,只需要改模型路径和输入输出的预处理逻辑,不需要动上层业务代码。

5. 实操部署与接口调用

这章是完全的实践向内容。我会给出部署步骤、启动命令、调用示例和性能调优方向,照着操作,从拿到代码到跑通接口,正常情况十几分钟就能搞定。

5.1 环境准备与依赖安装

部署环境建议用Linux服务器,Python版本要求3.9以上。主要依赖包括FastAPI、Uvicorn、OpenCV-Python、ONNX Runtime、NumPy、Pydantic。

创建虚拟环境后安装依赖:

python -m venv anticap_env source anticap_env/bin/activate pip install -r requirements.txt

如果是Windows环境,OpenCV和ONNX Runtime的wheel包需要单独确认版本匹配。我在Windows上部署时遇到过OpenCV导入报错的情况,多半是拿到了非官方构建的wheel包,建议优先用官方PyPI源安装。

模型文件需要注意:项目仓库里如果包含了模型文件,直接使用;如果只包含下载脚本,需要先执行模型下载命令。模型文件比较大,建议放到独立目录,并在config里指定模型路径。

5.2 启动服务

依赖装好后启动服务:

uvicorn main:app --host 0.0.0.0 --port 8000 --workers 2

启动参数的含义拆解一下:--host 0.0.0.0是监听所有网卡地址,这样其他机器也能访问;--port 8000是服务端口;--workers 2是启动两个Worker进程。我建议生产环境 workers 数不要超过CPU核心数,因为每个Worker会独立加载一份模型,内存开销不小。

启动后可以在浏览器打开 http://127.0.0.1:8000/docs 查看FastAPI自动生成的接口文档,也可以直接在线调试接口。这个内置文档在实际联调时帮了大忙,省去了手写测试请求的麻烦。

5.3 接口调用示例

我用一段Python代码演示完整调用过程:

import requests import base64 def recognize_slider(background_path, piece_path, api_url="http://127.0.0.1:8000/api/captcha/recognize"): with open(background_path, "rb") as f: bg_data = base64.b64encode(f.read()).decode() with open(piece_path, "rb") as f: piece_data = base64.b64encode(f.read()).decode() payload = { "type": "slider", "images": { "background": bg_data, "piece": piece_data }, "ext_params": { "background_width": 340, "background_height": 160 } } resp = requests.post(api_url, json=payload, timeout=10) return resp.json() # 示例:识别一张缺口滑块验证码 result = recognize_slider("bg.png", "piece.png") print(result)

返回示例:

{ "code": 0, "msg": "success", "data": { "target_x": 162, "target_y": 36, "distance": 118, "confidence": 0.97 }, "cost_ms": 240 }

拿到distance后,把它传给Selenium或Playwright的拖拽操作,就能完成后续动作。其他类型验证码调用方式类似,只改type参数和images结构即可。

5.4 并发与性能调优

性能是验证码识别服务必须考虑的问题。单个识别请求的耗时主要花在模型推理和图像处理上,OCR类平均200毫秒到300毫秒,滑块类平均300毫秒到400毫秒,点选类因为要跑目标检测再加语义匹配,耗时会到500毫秒以上。

如果单机吞吐量不够,优先做两个优化。第一个是升级硬件配置,CPU换成更高主频、更大缓存,对ONNX Runtime的CPU推理有明显帮助;有显卡的话把ONNX Runtime的ExecutionProvider设成CUDA,推理性能能提升数倍。第二个是增加Worker数量和异步队列长度,让请求尽可能并行处理,而不是排队串行。

我在某公司的生产环境实测过,双核CPU、4GB内存的服务器上,部署两个Worker,OCR类接口的稳定QPS在每秒10次左右。这个指标对绝大多数自动化脚本来说已经够用了。

6. 常见问题与排查技巧实录

最后把这半年多使用中遇到的高频问题整理成速查表,再单聊验证码更新后的应对思路。这些内容是我“用时间换出来”的经验,普通文档里不会写。

6.1 常见问题排查速查表

问题现象可能原因解决方法
接口返回401鉴权失败没有配置API Key或配置错误检查config文件里的api_key配置,确认客户端带了正确Header
OCR识别结果乱码图像预处理参数不适合当前验证码风格调整预处理参数,特别是二值化阈值和去噪强度
滑块缺口定位偏差大Canny阈值参数不适配切换为动态阈值模式,或在config中单独校准该站点参数
点选结果坐标为空目标检测模型对目标类型不敏感收集目标站点样本做增量训练,或尝试调整检测置信度阈值
启动时模型加载失败模型文件缺失或用错版本检查models目录完整性,重新下载匹配的模型文件
请求超时识别耗时过长或引擎死锁增大HTTP超时时间,检查识别引擎是否出现异常退出
并发高时响应变慢线程池或Worker数配置不足增加Worker数量,优化模型推理使用GPU
返回对比类验证码支持不行没反应接口没传对type字段核对文档确认type值和参数格式是否匹配

6.2 验证码更新后的应对思路

没有哪一种识别方案是万能的,验证码服务商不定期会更新样式、增加干扰、改变交互方式。我在项目中经历过几次验证码样式升级,最初的识别准确率直接掉到百分之三四十。这里分享一套应对方法论。

第一步是快速采集样本。发现准确率下降后,先手动下载或截取目标站点的新验证码图片,尽量多收集不同样本,几十张到一百张起步。

第二步是分析变化点。对比新旧图片,搞清楚是颜色背景变了,还是干扰线更密了,还是滑块缺口样式变化了。变化点对应的就是识别链路的薄弱环节。如果只是背景颜色变化,调整预处理参数即可;如果缺口样式重绘,可能需要重新标注训练数据。

第三步是针对性调优。如果算法还能识别但准确率低了,优先调整预处理参数和置信度阈值;如果完全识别不出来,就要收集训练数据做模型微调。我在这套服务里预留了“模型增量训练”的脚本入口,就是为了应对这种场景。

第四步是灰度验证。调优完成后不要直接全量切流,先拿一批真实请求做灰度测试,对比识别前后的业务成功率,确认稳定后再全量切换。

6.3 部署上的一些边界情况

如果你准备把这个服务放到公网,有一点必须做好——接口鉴权。我默认在配置里启用了API Key校验,客户端请求时需要在Header里带上密钥。别嫌麻烦,验证码识别接口一旦被滥用,轻则被刷爆流量,重则被目标站点封禁IP,得不偿失。

另外,不建议在生产环境直接使用默认配置。默认配置主要考虑了开箱即用,性能和并发能力都不是最优状态。上线前建议把日志输出格式、模型设备、Worker数量、超时时间都过一遍,按照实际场景调整。

我在实际项目里还有一个习惯,随手记录不同站点的识别成功率,做成简单的表格定期复盘。某公司站点A的滑块识别率稳定在96%,站点B的旋转验证码只有85%,复盘之后发现B站点的图片分辨率偏低,预处理阶段需要先做一次超分辨率增强,调优后准确率提升到了九成。这些数据和经验只有长期积累才能沉淀下来,也是我最终把它打包成完整项目分享出来的原因。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询