当前位置: 首页 > news >正文

【锦图简历】程序对简历扫描件的识别流程

在做简历上传功能时,我低估了一个场景:扫描件 PDF——用户从 scanner 或微信保存的 PDF,肉眼看正常,文本层却是空的。此时pdf-parse一类库几乎抽不出字,用户却认为「我上传没问题」。

下面是我们在线上用的分层提取 + OCR 回退思路,供同类文档上传场景参考。

1. 先判断:有没有可提取的文本层?

流程第一步不是 OCR,而是尽量便宜地拿文本

  1. 优先Poppler pdftotext(结构化参数:行阈值、单元格分隔)
  2. 回退pdf-parse多种提取模式
  3. 统计「有效字符数」(去空白后),低于阈值(如 80 字)→ 判定为扫描件

这样能避免对可复制 PDF 做昂贵的 OCR。

2. 扫描件:渲染 → OCR → 规整

判定为扫描件后:

PDF Buffer → pdftoppm / pdf-to-img(按页渲染,DPI 建议 300 左右) → 图像预处理(灰度、对比度、锐化、小图放大) → Tesseract(chi_sim+eng,PSM 3/11/6 择优) → 文本后处理(去乱码行、拆粘连章节) → 简历规整(章节换行、列表符、经历行) → 规则诊断 / AI 分析

PSM 说明(简版):

  • 3:全自动分页,适合整页简历
  • 11:稀疏文本,适合 bullet 列表
  • 6:单块文本,部分模板反而更好

可对同一页跑多种 PSM,用质量评分(有效字符比 + 章节词命中)选最优,而不是写死一种。

3. 工程踩坑(真实遇到过)
现象处理
Docker 缺语言包OCR 全乱码镜像预装chi_simeng
多页 OCR 超时用户以为卡死限最大页数 + 流式进度
Nginx 60s 断连上传到一半失败proxy_read_timeout;OCR 阶段发 keepalive
双栏 Word 模板左栏技能与右栏经历串行宽图分列 OCR + 后处理去噪(另文详述)
DPI 过低小字号中文漏字150 → 300,小图再放大
4. 进度与体验

OCR 单页可能 20~40 秒,整份 90 秒不罕见。不要只给一个 spinner

我们采用NDJSON 流式响应,步骤例如:extract → ocr → normalize → done,每步推送进度百分比与人话文案(「正在识别扫描版文字…」)。OCR 阶段长时间无业务输出时,额外发心跳行,避免代理认为连接空闲而断开。

5. 代码结构(示意)

不必照搬,关键是阶段可观测

// 伪代码:上传解析入口asyncfunctionparseResumeDocument(buffer,fileName){onStep("extract");consttextLayer=awaittryExtractText(buffer);if(hasEnoughText(textLayer)){onStep("normalize");returnformat(textLayer);}onStep("ocr");constocrText=awaitocrPdfPages(buffer);// poppler render + tesseractonStep("normalize");returnformat(cleanupOcr(ocrText));}
6. 结论
  • 扫描 PDF 在中文求职场景里不是边缘 case,是常态之一
  • 后端要能自动回退 OCR,并在 UI 上让用户等得明白
  • OCR 之后还要规整 + 人工校对,尤其双栏模板

我们在产品锦图简历里按上述链路实现简历上传(Word / 可复制 PDF / 扫描 PDF / 图片)。若你也在做文档类 ToC 工具,欢迎评论区交流 Poppler 与 Tesseract 在容器里的打包方式。

http://www.jsqmd.com/news/1098704/

相关文章:

  • 抖音视频下载神器:轻松保存无水印高清内容
  • 真诚互粉|技术博主抱团取暖,长期互访、互相成长
  • Beyond Compare 5永久激活:3步解决文件对比工具授权限制
  • 【AI应用实战-hermes】hermes介绍(一)
  • PC大型3A 角色扮演游戏(RPG)《怪物猎人物语3:命运双龙》网盘下载 免BIOS 中文版
  • TVA在具身智能全栈能力体系中的关键作用(3)
  • G-Helper:华硕笔记本的轻量级控制中心,三步告别臃肿系统
  • 我用AI写网文赚了100万
  • 阿里云图像搜索完整对接指南:从开通到API/SDK深度集成
  • Mac 新手必装工具清单:从效率、安全到清理维护的完整指南(2026 更新版)
  • YOLO26N 姿态估计模型训练全流程
  • 电力通信必备!IEC104主站模拟工具FreyrSCADA使用教程
  • 基于平均失真约束的信息率失真函数推导与MATLAB验证(P124302050朱悦)
  • LabVIEW VISA异步I/O提升吞吐量
  • TVA在具身智能全栈能力体系中的关键作用(9)
  • 010、RDN残差密集网络:连续记忆机制与特征重用的数学本质
  • 【Python工程化实战】LangChain / LlamaIndex 项目的工程化重构:从 Demo 到生产级系统的实战指南
  • LCD Image Converter:嵌入式资源生成架构的技术挑战与创新解决方案
  • YOLO26N 姿态估计 RKNN 部署:RK3588 NPU 实战
  • 3分钟彻底解决Windows和Office激活难题:KMS_VL_ALL_AIO完整操作指南
  • FreeRTOS任务挂起与恢复:从API调用到实战避坑,手把手教你玩转任务调度
  • 未来工程团队的5种角色:Claude Code之父的团队框架
  • 安装opengauss单实例轻量版数据库
  • puzzle(1131)指路罗马
  • Python判断数字?别被isdigit()坑了!浮点负数全阵亡
  • NOAA VIIRS 气溶胶光学厚度与粒径 EDR V3 数据集
  • item0(1):接地 2
  • 为什么监管锁真正有用的时候,往往不是锁机那一刻?
  • TypeScript项目局域网访问和GitHub提交和发布操作
  • linux环境docker-compose部署Clickhouse 集群