OCRmyPDF 批量处理实战:用 Python 脚本给扫描 PDF 批量添加可搜索文本层
【免费下载链接】OCRmyPDFOCRmyPDF adds an OCR text layer to scanned PDF files, allowing them to be searched项目地址: https://gitcode.com/GitHub_Trending/oc/OCRmyPDF
手上一堆扫描版 PDF,得挨个打开工具、选文件、等识别、存结果,既耗时又容易漏。OCRmyPDF 的批量处理脚本就是为这个场景准备的:它会递归找出目录下的每一个 PDF,一次性加上可搜索的 OCR 文本层,同时自动跳过已经含文本的文件,并把原始文件归档备份。接下来带你从零跑通这个脚本,讲清楚关键参数,再绕开几个常见坑。
快速上手
第一步:获取项目先把 OCRmyPDF 仓库克隆到本地,批量脚本就在misc/batch.py,你不需要改动项目源码,直接调用即可。
git clone https://gitcode.com/GitHub_Trending/oc/OCRmyPDF第二步:安装依赖脚本把 OCRmyPDF 当库来调用(import ocrmypdf),所以系统里要先装好它,各发行版都用系统包管理器直接装即可。
apt install ocrmypdf第三步:最小命令跑通完成前两步后,进入项目目录直接运行批处理脚本。不传参数时,脚本默认处理当前目录(Path())下的所有 PDF,日志写到项目根目录的ocr-tree.log。
python3 misc/batch.py第四步:换目录、换日志路径如果要处理别处的扫描件,把目录作为第一个参数传入;想把日志写到别处,再传第二个参数。两个参数都可以省略,按需组合。
python3 misc/batch.py /data/scans /data/scans/ocr-run.log核心能力拆解
递归扫描:深层文件夹里的 PDF 一个不漏
你的扫描件很少整齐地放在一个目录里,通常按客户、年份、项目分了好多层子文件夹。脚本用start_dir.glob("**/*.pdf")递归遍历整棵目录树,按扩展名收集文件。哪怕一个 PDF 藏在第四层子目录里,也会被找到并排进处理队列,你不用自己维护文件清单。
智能跳过:已有文本的 PDF 不会被重复识别
一批文件里经常混着已经识别过的。脚本在处理前先调用ocrmypdf.pdfa.file_claims_pdfa()检测文件是否已含文本层,命中就跳过;就算检测漏网,OCRmyPDF 抛出的PriorOcrFoundError也会被脚本捕获并记录。效果是你可以放心地对同一个目录反复运行,已处理的文件不会浪费时间,也不会被二次加工。
归档备份:原始扫描件自动留底
处理后你不想失去原始扫描件。脚本顶部的archive_dir变量指定备份根目录,处理前会用shutil.copy2把原文件复制过去,缺失的目录会自动创建;复制前先经filecompare对比,归档件和原件一致就跳过。效果是每份被处理的 PDF 都能找回原始版本,识别出问题时可以从备份重新处理。
异常容忍:个别坏文件跳过,不拖垮整批
扫描件里总有些"刺头":加密的、带数字签名的、本身已标记(tagged)的 PDF。脚本逐类捕获EncryptedPdfError、DigitalSignatureError、TaggedPDFError等异常,把跳过原因写进日志后继续下一个文件。效果是一个坏文件不会中断整批任务,跑完后翻日志就知道哪些被跳过、为什么跳过。
关键代码与参数速览
批处理的核心就是misc/batch.py里这一个循环,不到三十行:
for filename in start_dir.glob("**/*.pdf"): logging.info(f"Processing {filename}") if ocrmypdf.pdfa.file_claims_pdfa(filename)["pass"]: logging.info("Skipped document because it already contained text") else: archive_filename = archive_dir + str(filename) if len(archive_dir) > 0 and not filecompare(filename, archive_filename): logging.info(f"Archiving document to {archive_filename}") try: shutil.copy2(filename, posixpath.dirname(archive_filename)) except OSError: Path(posixpath.dirname(archive_filename)).mkdir(parents=True) shutil.copy2(filename, posixpath.dirname(archive_filename)) try: result = ocrmypdf.ocr(filename, filename, deskew=True) logging.info(result) except ocrmypdf.exceptions.EncryptedPdfError: logging.info("Skipped document because it is encrypted") # 其余 PriorOcrFoundError、DigitalSignatureError 等异常同理捕获白话解读:glob("**/*.pdf")负责递归找文件;file_claims_pdfa(...)返回pass说明文件已有文本层,直接跳过。真正的识别由ocrmypdf.ocr(filename, filename, deskew=True)完成,定义在 src/ocrmypdf/api.py 中——两个文件名相同表示"原地覆盖",输出直接写回原文件;deskew=True表示先校正倾斜的页面再识别,歪斜扫描件的文本层会更准,OCRmyPDF 支持的其他参数(如language、image_dpi)也能在这里按需加上。另外两个变量值得留意:archive_dir默认是/pdfbak,改成空字符串""就关闭备份;日志以追加模式(filemode="a")写入,每次运行都会继续往下记。
场景实战
财务:把一年发票扫描件变成可检索档案
你是财务,每月收到上百份发票扫描件,月底被追问某笔报销时只能逐份翻找。把某个月的扫描 PDF 丢进一个目录,跑一遍python3 misc/batch.py,所有发票都会带上可搜索文本层,原件同步归档。收益是可以验证的:之后在 PDF 阅读器里按金额、供应商关键词直接搜索定位,不再靠肉眼翻页。
研究团队:整库扫描文献一次到位
研究生手头有一批扫描版论文 PDF,想复制引用原文做笔记,但复制出来是空白。把整个文献目录树交给批处理脚本:已含文本的文件自动跳过,扫描件统一识别,重复运行也安全。收益是处理完可以直接选中、复制 PDF 里的文字,省去重新敲引用的时间。
档案部门:数字化整柜纸质档案
档案室有成箱的纸质档案扫描件,要求原件绝对不动。把archive_dir改到内网归档盘的路径,脚本会先把原件复制进归档目录、再原地做 OCR,整个流程有日志可追溯。收益是原始扫描件始终完好在位,数字化后的文件即可入库、检索、长期保存。
避坑指南
加密文件被静默跳过,日志里只有半句话
现象:任务跑完,个别文件没变化,日志里只有Skipped document because it is encrypted。原因:脚本对需要密码的 PDF 是刻意跳过,不会尝试解密。解法:在ocr-tree.log中搜索encrypted定位文件,先给这些文件去掉密码,再单独对它们所在目录重跑一次:
python3 misc/batch.py /data/scans/decrypted备份目录 /pdfbak 权限不足,或相对路径拼错位置
现象:备份文件没出现在预期位置,甚至报权限错误。原因有两个:其一,archive_dir默认硬编码为/pdfbak,这是个系统级路径,脚本虽会自动创建缺失目录,但你对根目录可能没有写权限;其二,备份路径是archive_dir + str(filename)直接字符串拼接,第一个参数传相对路径时拼出来的结果不是你以为的路径。解法:不需要备份就改成archive_dir = "";需要备份则换成你有写权限的绝对路径,且第一个参数始终传绝对路径:
python3 misc/batch.py /data/web/scans日志文件悄悄变大,位置也容易找错
现象:ocr-tree.log越跑越大,或者你一直在 misc 目录里翻不到它。原因:日志默认追加写入,且默认位置是项目根目录(脚本所在目录的上一级)下的ocr-tree.log。解法:给第二次运行传一个独立的日志路径,按批次分开记录,旧文件也不再互相干扰:
python3 misc/batch.py /data/web/scans /data/web/scans/ocr-batch-01.log收尾
一个misc/batch.py就覆盖了"递归查找、智能跳过、备份归档、异常容忍、全程留痕",开头那堆需要挨个处理的扫描件,交给它跑一遍即可。如果你的文件更多、想并发加速,仓库里还有现成资料可以继续读:
- docs/batch.md:官方批处理文档,含用 GNU Parallel 并发跑
ocrmypdf的示例 - misc/batch.py:脚本本体,注释里明确欢迎你按需改写
脚本文件头那句 "You should edit this script to meet your needs" 就是这个意思——改两行变量,它就是你的专用工具。
【免费下载链接】OCRmyPDFOCRmyPDF adds an OCR text layer to scanned PDF files, allowing them to be searched项目地址: https://gitcode.com/GitHub_Trending/oc/OCRmyPDF
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考