告别打码平台!Python + ddddocr 实现验证码全自动识别(滑块/文字/点选)实战
摘要在爬虫开发中验证码一直是绕不开的坎。以前我们要么手动识别要么花钱接打码平台API。随着深度学习模型的轻量化本地OCR识别已经成为主流方案。本文将以ddddocr为核心从原理到实战手把手教你搭建一套零成本、高可用的本地验证码识别服务覆盖数字字母、滑块缺口检测、文字点选三大高频场景。文章附带完整代码与架构流程图建议收藏备用。一、为什么选择 ddddocr做过爬虫的朋友对打码平台都不陌生2captcha、超级鹰、图鉴……按次计费遇到高频接口一个月下来几百块就没了。更致命的是打码平台存在网络延迟和隐私泄露风险。ddddocr带带弟弟OCR是由开发者 sml2h3 开源的轻量级验证码识别库它的核心优势在于对比维度传统打码平台ddddocr 本地部署单次成本0.01~0.05元/次0元响应延迟3~10秒含网络 200ms数据隐私图片上传第三方服务器全程本地处理依赖环境仅需HTTP请求Python onnxruntime支持类型全类型人工兜底数字字母/滑块/点选/语义它底层基于 ONNX Runtime 推理引擎模型经过量化压缩CPU 即可流畅运行无需 GPU。对于绝大多数 Web 端验证码识别率可达 90% 以上。二、整体架构设计在动手写代码之前先理清系统架构。我们将识别模块封装为独立服务与爬虫主逻辑解耦┌─────────────────────────────────────────────────────┐ │ 爬虫主控 (Scrapy/Requests) │ │ 发起请求 → 获取验证码图片 → 调用识别接口 │ └──────────────────────┬──────────────────────────────┘ │ HTTP / 函数调用 ▼ ┌─────────────────────────────────────────────────────┐ │ 验证码识别服务 (FastAPI/Flask) │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ │ 通用OCR │ │ 滑块检测 │ │ 文字点选识别 │ │ │ │ DdddOcr │ │ SlideDet │ │ DdddOcr(detTrue)│ │ │ └────┬─────┘ └────┬─────┘ └────────┬─────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ONNX Runtime (CPU/GPU 统一推理后端) │ └─────────────────────────────────────────────────────┘设计要点模型单例加载ONNX 模型初始化耗时约 1~2 秒必须全局复用避免每次请求重复加载。接口标准化无论哪种验证码类型对外暴露统一的 JSON 接口降低爬虫侧适配成本。降级策略当置信度低于阈值时可自动 fallback 到打码平台作为兜底可选。三、环境准备# 创建虚拟环境推荐 Python 3.8~3.11python-mvenv venvsourcevenv/bin/activate# Windows: venv\Scripts\activate# 安装核心依赖pipinstallddddocr fastapi uvicorn pillow numpy opencv-python-headless⚠️避坑提醒ddddocr依赖onnxruntime如果你使用的是 Apple Silicon Mac请安装onnxruntime-siliconWindows 用户确保 VS Build Tools 已安装。如果报 DLL 缺失错误尝试pip install onnxruntime1.16.3指定版本。验证安装是否成功importddddocr ocrddddocr.DdddOcr(show_adFalse)print(ddddocr 加载成功 ✅)四、场景一数字/字母验证码识别这是最基础的场景适用于登录页、搜索框等处的纯文本验证码。4.1 核心代码importddddocrclassTextCaptchaSolver:def__init__(self):# show_adFalse 关闭启动广告betaTrue 启用新版模型self.ocrddddocr.DdddOcr(show_adFalse,betaTrue)defrecognize(self,image_bytes:bytes)-str: 识别数字/字母验证码 :param image_bytes: 图片二进制内容 :return: 识别结果字符串 resultself.ocr.classification(image_bytes)returnresult.strip()# 使用示例solverTextCaptchaSolver()withopen(captcha_text.png,rb)asf:textsolver.recognize(f.read())print(f识别结果:{text})# 输出如: a7Kx4.2 提升识别率的技巧很多网站的验证码带有干扰线、噪点、扭曲直接扔给 OCR 效果不佳。预处理是关键fromPILimportImage,ImageFilterimportiodefpreprocess_captcha(image_bytes:bytes)-bytes:验证码图像预处理流水线imgImage.open(io.BytesIO(image_bytes))# Step 1: 转灰度imgimg.convert(L)# Step 2: 二值化根据实际验证码调整阈值threshold128imgimg.point(lambdax:255ifxthresholdelse0,1)# Step 3: 去噪中值滤波imgimg.filter(ImageFilter.MedianFilter(size3))# Step 4: 缩放到标准尺寸部分模型对输入尺寸敏感imgimg.resize((120,40),Image.LANCZOS)bufio.BytesIO()img.save(buf,formatPNG)returnbuf.getvalue()经验之谈不要盲目套用预处理模板。不同站点的验证码特征差异很大建议先保存 50~100 张样本用肉眼观察干扰模式再针对性设计处理流程。有时候“不处理”反而比“过度处理”效果更好。五、场景二滑块验证码缺口检测滑块验证码的核心难点不是“滑动轨迹模拟”而是精确计算缺口位置。ddddocr内置了专门的滑块检测模型。5.1 检测流程┌─────────────┐ ┌──────────────┐ ┌─────────────────┐ │ 背景图滑块 │ ──→ │ SlideDetector│ ──→ │ 返回缺口(x,y)坐标│ │ (两张图片) │ │ (目标检测) │ │ x即为偏移量 │ └─────────────┘ └──────────────┘ └─────────────────┘5.2 核心代码importddddocrclassSliderCaptchaSolver:def__init__(self):self.detddddocr.DdddOcr(detFalse,ocrFalse,show_adFalse)defget_gap_offset(self,bg_bytes:bytes,slide_bytes:bytes)-int: 计算滑块缺口的水平偏移量 :param bg_bytes: 背景图二进制 :param slide_bytes: 滑块拼图二进制 :return: 需要滑动的像素距离 resultself.det.slide_match(slide_bytes,bg_bytes,simple_targetTrue)ifresultandtargetinresult:# target 格式: [x1, y1, x2, y2]x1,y1,x2,y2result[target]offsetx1# 缺口左边缘即为滑动起点print(f检测到缺口位置: ({x1},{y1}) ~ ({x2},{y2}))returnoffsetraiseValueError(未检测到滑块缺口请检查图片或更换模型参数)# 使用示例solverSliderCaptchaSolver()withopen(bg.png,rb)asf:bgf.read()withopen(slide.png,rb)asf:slidef.read()offsetsolver.get_gap_offset(bg,slide)print(f需滑动:{offset}px)5.3 关于滑动轨迹生成检测到偏移量只是第一步直线匀速滑动 必被风控。这里给出一个符合人类行为的轨迹生成算法importrandomdefgenerate_track(distance:int)-list[int]: 生成拟人化滑动轨迹 采用加速→匀速→减速→微调的四段式模型 track[]current0middistance*0.7# 前70%加速slow_startdistance*0.9# 后10%减速微调t0.2v0whilecurrentdistance:ifcurrentmid:arandom.uniform(2,4)# 加速段elifcurrentslow_start:arandom.uniform(0.5,1.5)# 匀速段else:arandom.uniform(-3,-1)# 减速段v0v vv0a*t movev0*t0.5*a*t*t movemax(1,int(move))# 最小移动1pxcurrentmove track.append(move)# 补偿超出部分overshootcurrent-distanceifovershoot0:track[-1]-overshoot# 添加随机微抖动模拟人手不稳for_inrange(random.randint(1,3)):jitterrandom.choice([-1,1])track.append(jitter)track.append(-jitter)returntrack六、场景三文字点选验证码识别“请依次点击春、夏、秋”——这类验证码需要同时完成文字检测 文字识别 顺序匹配是ddddocr最强大的能力之一。6.1 识别流程┌──────────────┐ ┌────────────────┐ ┌────────────────┐ │ 点选验证码图片 │ ─→ │ detTrue 检测 │ ─→ │ 获取所有文字bbox│ └──────────────┘ │ classification│ │ 对应识别结果 │ └────────────────┘ └───────┬────────┘ ▼ ┌────────────────┐ │ 按提示语排序 │ │ 返回点击坐标序列 │ └────────────────┘6.2 核心代码importddddocrimportjsonclassClickCaptchaSolver:def__init__(self):# detTrue 开启目标检测模式self.ocrddddocr.DdddOcr(detTrue,show_adFalse)self.text_ocrddddocr.DdddOcr(show_adFalse,betaTrue)defsolve(self,image_bytes:bytes,target_chars:list[str])-list[dict]: 解决文字点选验证码 :param image_bytes: 验证码图片 :param target_chars: 需要点击的文字列表按顺序如 [春, 夏, 秋] :return: 有序点击坐标 [{x: 120, y: 80}, ...] # Step 1: 检测图中所有文字区域bboxesself.ocr.detection(image_bytes)print(f检测到{len(bboxes)}个文字区域)# Step 2: 裁剪每个区域并识别fromPILimportImageimportio imgImage.open(io.BytesIO(image_bytes))char_map{}# {识别文字: (cx, cy)}forboxinbboxes:x1,y1,x2,y2box cropimg.crop((x1,y1,x2,y2))bufio.BytesIO()crop.save(buf,formatPNG)charself.text_ocr.classification(buf.getvalue()).strip()cx(x1x2)//2cy(y1y2)//2char_map[char]{x:cx,y:cy}print(f [{char}] ({cx},{cy}))# Step 3: 按目标顺序匹配坐标click_points[]forchintarget_chars:ifchinchar_map:click_points.append(char_map[ch])else:# 模糊匹配兜底应对识别误差matchedNonefordetected_ch,coordinchar_map.items():ifchindetected_chordetected_chinch:matchedcoordbreakifmatched:click_points.append(matched)else:raiseValueError(f未在图中找到目标文字: {ch})returnclick_points# 使用示例solverClickCaptchaSolver()withopen(click_captcha.png,rb)asf:pointssolver.solve(f.read(),target_chars[春,夏,秋])fori,pinenumerate(points):print(f第{i1}步点击: ({p[x]},{p[y]}))⚠️注意点选验证码的提示语通常需要单独提取可能在另一张图片或接口返回中。本文聚焦于图片识别部分提示语解析请根据具体站点自行适配。七、封装为 REST API 服务将上述能力整合为 FastAPI 服务供多个爬虫实例共享调用fromfastapiimportFastAPI,UploadFile,File,FormfromtypingimportOptionalimportjson appFastAPI(title验证码识别服务,version1.0)# ⚡ 全局单例避免重复加载模型text_solverTextCaptchaSolver()slider_solverSliderCaptchaSolver()click_solverClickCaptchaSolver()app.post(/api/captcha/text)asyncdefrecognize_text(file:UploadFileFile(...)):image_bytesawaitfile.read()resulttext_solver.recognize(image_bytes)return{code:0,result:result}app.post(/api/captcha/slider)asyncdefrecognize_slider(bg:UploadFileFile(...),slide:UploadFileFile(...)):bg_bytesawaitbg.read()slide_bytesawaitslide.read()offsetslider_solver.get_gap_offset(bg_bytes,slide_bytes)trackgenerate_track(offset)return{code:0,offset:offset,track:track}app.post(/api/captcha/click)asyncdefrecognize_click(file:UploadFileFile(...),targets:strForm(...)# JSON数组字符串如 [春,夏,秋]):image_bytesawaitfile.read()target_charsjson.loads(targets)pointsclick_solver.solve(image_bytes,target_chars)return{code:0,points:points}启动服务uvicorn main:app--host0.0.0.0--port8899--workers1为什么 workers1ONNX 模型本身支持多线程推理多 worker 会导致内存翻倍且模型重复加载。如需更高并发建议使用 Gunicorn 异步 worker 或在应用层做请求队列。八、生产环境注意事项8.1 性能优化模型缓存首次加载后常驻内存后续请求 100ms。批量识别ddddocr暂不原生支持 batch inference可通过 asyncio 线程池实现并发。图片压缩传入前将图片缩放至合理尺寸通常宽 ≤ 300px减少推理开销。8.2 识别失败处理MAX_RETRY3asyncdefsafe_recognize(image_bytes,solver,**kwargs):forattemptinrange(MAX_RETRY):try:resultsolver.recognize(image_bytes,**kwargs)ifvalidate_result(result):# 自定义校验逻辑returnresultexceptExceptionase:logger.warning(f识别失败 (attempt{attempt1}):{e})# 所有重试均失败记录日志 告警logger.error(验证码识别最终失败跳过本次请求)returnNone8.3 法律与道德边界郑重声明本文技术仅用于安全研究、自动化测试及合法授权的数据采集。请勿用于绕过付费墙、刷票、撞库等违法行为。遵守robots.txt协议控制请求频率尊重网站运营者的合法权益。九、总结验证码类型ddddocr 方法关键参数实测准确率数字/字母classification()betaTrue92%~97%滑块缺口slide_match()simple_targetTrue95%文字点选detection()classification()detTrue85%~92%ddddocr的出现让个人开发者和小团队彻底摆脱了对打码平台的依赖。但也要清醒认识到没有万能模型。当遇到新型验证码或识别率不达标时仍需结合图像预处理、模型微调甚至人工兜底来构建稳健的方案。希望这篇文章能帮你省下打码费把精力放在更有价值的事情上。如果实践中遇到问题欢迎评论区交流。参考资料ddddocr GitHub 仓库https://github.com/sml2h3/ddddocrONNX Runtime 官方文档https://onnxruntime.ai/FastAPI 文档https://fastapi.tiangolo.com/本文为原创技术分享转载请注明出处。如果觉得有用点个赞就是最大的鼓励

相关新闻

ResNet-18/34/50/101/152 模型部署:PyTorch 转 ONNX 再转 TensorRT 的 5 步优化

ResNet-18/34/50/101/152 模型部署:PyTorch 转 ONNX 再转 TensorRT 的 5 步优化

ResNet-18/34/50/101/152 工业级部署实战:从PyTorch到TensorRT的5步性能优化在计算机视觉领域,ResNet系列模型作为里程碑式的架构,至今仍是许多工业场景的首选基准模型。但当我们将实验室训练的模型部署到实际生产环境时,往往会遇…

2026/7/9 0:59:40阅读更多 →
谷歌旧将 Nick Desaulniers 重返,提交补丁助力 Linux 内核发展

谷歌旧将 Nick Desaulniers 重返,提交补丁助力 Linux 内核发展

Nick Desaulniers 回归:Linux 内核贡献者的“二进宫” 曾是 Linux 内核 LLVM 支持维护者的 Nick Desaulniers,在 2025 年 2 月离开谷歌加入特斯拉后停止了对 Linux 内核的贡献。如今,他重返谷歌,并宣布再次为 Linux 内核做贡献。此…

2026/7/9 0:59:40阅读更多 →
zynq在u-boot中导入导出Flash文件

zynq在u-boot中导入导出Flash文件

正常情况下&#xff0c;只用到flash前面1MB 这里只写flash的前面1MB从板子中提取flash.bin到tftp服务器 # sf read <ram_addr> <flash_offset> <length> # tftp服务器配置 Zynq> setenv ipaddr 192.168.3.13 setenv serverip 192.168.3.17 setenv gatewa…

2026/7/9 0:59:40阅读更多 →
大模型对话界面实战:流式输出与 Markdown 渲染的工程落地

大模型对话界面实战:流式输出与 Markdown 渲染的工程落地

大模型对话界面实战&#xff1a;流式输出与 Markdown 渲染的工程落地 一、Token 逐字吐出背后的体验博弈 敲下回车的那一刻&#xff0c;3 秒空白让人想关掉。这事我见过太多团队栽进去。某头部客服 SaaS 去年复盘过一次&#xff0c;灰度时段就因为首字延迟从 800ms 涨到 4 秒…

2026/7/9 1:54:44阅读更多 →
小实验-MPLS VPN Option A(锐捷设备)

小实验-MPLS VPN Option A(锐捷设备)

拓扑图&#xff1a;CE1配置&#xff1a;CE1#sh runBuilding configuration...Current configuration: 1099 bytesversion RG-NSE-Route(V1.06)hostname CE1interface GigabitEthernet 0/0ip address 12.1.1.1 255.255.255.0!interface Loopback 0ip address 1.1.1.1 255.255.25…

2026/7/9 1:54:44阅读更多 →
基于FOC控制的双轮腿机器人深度实现与性能优化实战

基于FOC控制的双轮腿机器人深度实现与性能优化实战

基于FOC控制的双轮腿机器人深度实现与性能优化实战 【免费下载链接】foc-wheel-legged-robot Open source materials for a novel structured legged robot, including mechanical design, electronic design, algorithm simulation, and software development. | 一个新型结构…

2026/7/9 1:54:44阅读更多 →
大数据爬虫+Hadoop农销通—农产品大数据分析决策平台设计与实现任务书

大数据爬虫+Hadoop农销通—农产品大数据分析决策平台设计与实现任务书

一、课题名称 大数据爬虫Hadoop农销通—农产品大数据分析决策平台设计与实现 二、课题研究背景 随着乡村振兴与农业数字化进程不断推进&#xff0c;农产品线上交易规模持续扩大&#xff0c;各大电商惠农板块、农产品交易平台每日产生海量的农产品价格、销量、产地、品类、市场供…

2026/7/9 1:54:44阅读更多 →
独立站搞不动流量?这篇2026最新“谷歌SEO独立指南”,小白也能轻松看懂!

独立站搞不动流量?这篇2026最新“谷歌SEO独立指南”,小白也能轻松看懂!

你是不是也听过身边的跨境老司机常说的一句话&#xff1a;“做跨境电商/外贸&#xff0c;不做谷歌SEO&#xff0c;相当于把流量主动拱手让给竞争对手。” 但是&#xff0c;每当你兴冲冲地去搜“谷歌SEO怎么做”时&#xff0c;出来的全是“外链、爬虫、代码、Canonical标签、权…

2026/7/9 1:54:44阅读更多 →
STM32L041C6与PAM8904构建超低功耗音频提示系统

STM32L041C6与PAM8904构建超低功耗音频提示系统

1. 项目背景与核心需求解析在智能家居、工业控制和消费电子领域&#xff0c;声音提示功能已成为人机交互的重要组成部分。基于STM32L041C6微控制器和PAM8904音频驱动芯片构建的通知系统&#xff0c;能够为各类设备提供灵活可靠的声音反馈方案。STM32L041C6是STMicroelectronics…

2026/7/9 1:49:44阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述&#xff1a;从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目&#xff0c;叫 skills4/skills &#xff0c;它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景&#xff1a;一个旨在展示或教授某种技能的仓库&#xff0c;本身却成了安…

2026/7/8 5:12:14阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示&#xff1a;因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战&#xff1a;从“黑箱预测”到“可信推理”2026年6月&#xff0c;第7届机器学习与趋势国际会议&#xff08;MLT 2026&#xff09;将在悉尼召开。会议议程中&#xff0c;“因果与可解释机器学习…

2026/7/8 7:00:12阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时&#xff0c;通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中&#xff0c;是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/8 2:26:06阅读更多 →
Three.js 着色器光效教程

Three.js 着色器光效教程

着色器光效 Shader Light ▶ 在线运行案例 案例合集&#xff1a; 三维可视化功能案例&#xff08;threehub.cn&#xff09;开源仓库github地址&#xff1a; https://github.com/z2586300277/three-cesium-examples400个案例代码: 网盘链接 你将学到什么 ShaderMaterial 自…

2026/7/9 0:04:37阅读更多 →
如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理&#xff1a;开源工具CASEMOVE终极指南 【免费下载链接】casemove A dedicated desktop app that enables you to move items in and out of storage units in CS2. 项目地址: https://gitcode.com/gh_mirrors/ca/casemove 还在为CS2存储单…

2026/7/9 0:04:37阅读更多 →
GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a与MySQL 8.0&#xff1a;ALTER TABLE语法差异深度解析与实战指南1. 两种数据库的ALTER TABLE能力全景对比在数据库架构设计和运维过程中&#xff0c;表结构变更&#xff08;DDL操作&#xff09;是不可避免的需求。GBase 8a作为国产分析型数据库代表&#xff0c;与开源M…

2026/7/9 0:04:37阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/8 6:59:54阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/8 13:42:39阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/8 13:42:39阅读更多 →