结论先说:几万份扫描 PDF 要跑完 OCR,瓶颈几乎从来不是「选哪个 OCR 引擎」本身,而是有没有在开工前分流、有没有并行、有没有可恢复的任务队列。单机用 GUI 一个个转,一万份可能要几周;按本文的流水线在 8~16 核 VPS 或带 GPU 的 Worker 上跑,同样体量通常能压到数小时到一两天——前提是接受「先快筛、再精 OCR、坏页隔离」的工程取舍,而不是追求每页都上最贵模型。
本文面向档案数字化、法务卷宗、医疗影像报告、历史论文库、企业合同扫描件等场景:文件量在 1 万~10 万+,多数是纯扫描或混合 PDF。关键词:批量 OCR、扫描 PDF 识别、ocrmypdf、PaddleOCR。若你之后要把识别结果灌进 RAG,导入前的类型判定与质量检查请直接看 RAG PDF Parsing 最佳实践——OCR 只是整条链路的第一段。
数据核对日期:2026 年 8 月 8 日。命令与参数以 OCRmyPDF 官方文档、Tesseract 文档 与 PaddleOCR 仓库 当前版本为准。
为什么「批量扫描 PDF」容易慢到无法接受
很多人第一次批量 OCR 的失败模式很相似:把文件夹丢进某个桌面工具,发现 CPU 只占 15%、风扇不响、一晚上只跑了 200 份。根因通常是下面几条叠在一起:
- 串行处理:一个进程按文件顺序跑,多核机器空转。
- 没做预检:30% 文件其实已有文字层,仍走完整 OCR,白白烧时间。
- 按「文件」并行而非按「页」:单份 800 页的卷宗占满一个 Worker,其他核闲着;小文件又频繁启停进程。
- 输出格式过重:每页 OCR 后重新压图、嵌字体、做 PDF/A,IO 和 CPU 双爆。
- 没有断点续跑:跑到第 9000 份崩溃,从头再来。
几万份的规模下,流水线设计比 OCR 引擎微调重要一个数量级。下面按「最快落地」顺序写:先 10 分钟能跑起来的方案,再讲到万级吞吐的架构。
第 0 步:预检分流——别对不需要 OCR 的文件动手
在跑任何 OCR 之前,用脚本批量扫一遍目录(find + parallel 或 Python 多进程均可):
- 用 PyMuPDF /
pdfinfo统计每页get_text()字符数;连续可读文字超过阈值(例如 80 字/页)的标记为text_layer,直接复制到输出目录,不走 OCR。 - 加密 PDF、0 页损坏文件写入
quarantine/,别卡死整个队列。 - 对混合 PDF(封面扫描 + 内文可选文字)按页级打标签,后续只 OCR 需要的页——这是万级体量省时间的大头。
我们见过一个法务项目:库内 4.2 万份 PDF,预检后发现 38% 已有合格文字层、12% 加密需人工处理,真正需要 OCR 的只有约 50%。这一步把总工时直接砍半,比换「更准的 OCR 模型」见效快得多。
经验值:预检脚本应输出 CSV(路径、页数、类型、预估 OCR 页数)。后续队列按「OCR 页数」而不是「文件数」估时,排期才靠谱。
最快能跑起来的方案(1 千~5 千份)
若你今天要交差、机器是一台 8 核 Linux 或云端 VPS,推荐这条最少依赖路径:
- 安装
ocrmypdf+ Tesseract(中文加chi_sim/chi_tra语言包)。 - 用
GNU parallel或xargs -P按文件并行,并发数设为 CPU 核数 − 1(留一核给 IO)。 - 参数建议:
--skip-text(跳过已有文字层)、--optimize 0或低优化等级(先求速度)、--jobs 1在每个 ocrmypdf 进程内避免过度嵌套并行。 - 输出先写到本地 SSD 临时目录,批量完成后再
rsync到对象存储——网络盘边写边传会拖垮吞吐。
cat scan_only.txt | parallel -j 8 \
'ocrmypdf --skip-text --optimize 0 --language chi_sim+eng \
{} /data/ocr_out/{/.}.pdf'
中文为主的扫描件,Tesseract 准确率往往不如 PaddleOCR,但装包 5 分钟、今晚就能跑。若识别率不够,再对「低置信度页」二次走 PaddleOCR,而不是全盘重跑。
万级体量架构:队列 + Worker + 断点续跑
当文件数到 1 万~10 万+,必须把「一次性的 shell 循环」升级成可观测的任务系统:
- 任务队列:Redis + RQ、Celery、或云厂商的 Batch / Step Functions。每条任务 = 一个 PDF 或一个「页范围」(大文件切片)。
- 状态表:SQLite / Postgres 记录
file_hash、状态(pending / running / done / failed)、重试次数、OCR 引擎版本。崩溃后只重跑failed。 - Worker 水平扩展:单机 8 Worker 不够就起第二台 VPS;OCR 是 CPU 密集,多台中配机器通常比一台巨型机划算。
- 页级并行(大卷宗):单 PDF > 200 页时,先
pdftoppm拆页图,页图丢进队列,OCR 完再合并文字层——避免一个巨文件霸占 Worker 三小时。 - GPU 分支:PaddleOCR、Surya、部分商用 API 在 GPU 上页吞吐可翻数倍;建议单独 GPU Worker 池,与 Tesseract CPU 池分流,按语言/版式路由。
编排层不必一开始就用 Kubernetes。很多团队在 2~4 台 VPS Worker 上跑 Docker Compose + Redis 就够用:一台放队列与元数据,其余纯 OCR。等日处理量稳定超过单机上限再加机器,比 premature K8s 省事。
工具怎么选:速度、中文、可搜索 PDF
| 方案 | 适合场景 | 吞吐特点 | 注意点 |
|---|---|---|---|
| OCRmyPDF + Tesseract | 欧美文为主、要标准可搜索 PDF | CPU 并行友好、部署简单 | 中文复杂版式准确率一般 |
| PaddleOCR(自托管) | 中文/中英混排、表格多 | GPU 加速后页级很快 | 需自己拼 PDF 文字层回写 |
| ocrmypdf + 外部引擎 | 已有定制 OCR 服务 | 接口统一 | 注意授权与 QPS 限制 |
| 商用 API(Azure DI、ABBYY 等) | 合规要求高、不愿自运维 | 按页计费、弹性好 | 几万页成本要事先算账 |
最快不等于最省:商用 API 往往「上线最快、账单最大」;自托管 PaddleOCR 前期搭环境慢,但 10 万页摊下来常更便宜。团队应拿 200 份代表性样本做准确率 × 单页耗时 × 单价三角评测,而不是看营销文案里的「99% 准确率」。
再抠 30%~50% 速度的实操技巧
- 降 DPI 再 OCR:扫描存档若是 600 DPI,先试 300 DPI 渲染再识别——很多合同/报告 300 已够,页渲染时间几乎减半。
- 灰度 / 二值化预处理:干净黑白扫描用 OpenCV 去噪+自适应阈值,可减少 Tesseract 误识别重试。
- 语言包最小化:只加载
chi_sim+eng,别默认加载十几种语言。 - 跳过低价值页:空白页、纯印章页用像素方差检测后直接标记
skip。 - 输出策略:若下游只要全文检索,可额外导出
.txt/.jsonl(按页),不必每份都生成重量级 PDF/A;需要归档的再走慢路径。 - 本地 NVMe 临时盘:云主机系统盘若是网络盘,把
TMPDIR挂到本地 SSD 卷,IO 等待会明显下降。
速度与质量怎么同时兜住
批量跑完后,别直接宣布成功。建议自动化质检抽样:
- 随机抽 0.5% 文件人工对读,或对比原图与 OCR 文本的 CER(字符错误率)。
- 对数字密集页(发票号、案号、日期)做正则校验,异常率超阈值整批标记
review。 - 记录每页平均置信度(Tesseract
tsv、Paddle 分数),低分页进二次 OCR 队列。
这与 RAG 场景的「黄金样本集」是同一思路:OCR 是一次性成本,坏数据进库后的检索修复成本更高。档案场景则要留审计日志——谁、何时、用什么引擎版本处理了哪份文件。
粗算:几万份要多少机器和时间
假设预检后需 OCR 的共 5 万页,单核 Tesseract 约 3~8 秒/页(视 DPI 与语言而定),取中值 5 秒:
- 单核串行:约 69 小时。
- 8 核满载并行(8 路文件):约 8~12 小时(含 IO 损耗)。
- 2 台 8 核 Worker:约 4~6 小时。
- 单张 T4 GPU + PaddleOCR:常见可到 1~3 秒/页量级,5 万页约 14~42 小时单卡——多卡线性扩展。
以上是量级估算,不是承诺 SLA。真正排期请用你自己的 100 页样本实测 pages_per_hour,再乘剩余页数。并发不是越高越好:磁盘、内存和临时文件句柄会先成为瓶颈,一般在每核 1 个 OCR 进程附近收益最大。
可抄作业的批量 OCR 清单
- 递归清单 + SHA256 去重,写 manifest。
- 预检分流:
text_layer/scan/mixed/encrypted。 - 队列入队(优先小文件或按 OCR 页数均衡)。
- Worker 并行 OCR,
--skip-text或页级路由。 - 输出可搜索 PDF 或 sidecar 文本 + 元数据 JSON。
- 抽样质检 + 低置信度二次处理。
- 归档到对象存储,manifest 标记
ocr_engine_version便于日后重跑。
若 OCR 结果下一步要进向量库,请把「解析版本号」和「页级类型」一并写入元数据——日后换引擎重跑时不用猜哪些 chunk 已过期。长文档问答成本还可结合 Context Caching 成本估算 控制推理账单。
最后一句
几万份扫描 PDF 没有银弹,但有可复制的最快路径:预检砍掉一半无效 OCR → 队列保证可恢复 → 多 Worker 吃满 CPU/GPU → 质检拦住坏页。先让流水线跑通、再调引擎参数;反过来会在第一周就耗尽耐心。
批量 OCR 占满 CPU?把 Worker 放到云端
几万页识别是典型「算力批处理」:笔记本不适合 72 小时满载,但在 Linux VPS 或带 GPU 的云端 Worker 上可以水平扩展、断点续跑。开发者在 Cloud Mac 上做脚本调试与质检抽样,重活交给队列后的 OCR 节点——本机安静、队列不堵。VPSSpark 提供按场景选型的云端开发环境与 VPS 资源,适合档案数字化与知识库建设的长跑任务。