(文末附有完整源代码及文档)
每到报销季,装发票的文件夹总会先乱起来。
几十张发票混在一起,文件名有的是一串数字,有的是“电子发票.pdf”,还有一些干脆来自微信临时下载。整理的人需要逐张打开,找到日期、金额和发票号码,再改名、归档、做明细表。
这些动作有明确规则,而且会反复发生,可以交给程序处理。
于是我利用 Python 和 百度的 OCR 功能做了一个发票整理工具,它可以读取 PDF、OFD 和图片发票中的字段,按统一规则生成文件名,并导出 Excel 明细表。
对于无法使用百度服务的场景,该工具也支持本地图像识别。“自动整理发票”可以拆成几个步骤:
这些步骤需要分开处理,否则更换 OCR 服务或增加文件格式时,容易影响命名和导出逻辑。
因此,我们先确定输入、输出和中间数据,再选择具体的 OCR 方案。
输入是 PDF、OFD 或图片,输出是一份结构化明细表和可选的重命名发票副本。百度和本地模型分别负责提供字段。批量处理时,每个文件独立完成,单张识别失败不会中断整批任务。
OCR 返回的一段文字不能直接用于归档,程序还需要得到固定字段,例如:
百度增值税发票接口会直接返回这些结构化字段。程序将接口结果转换为自己的数据模型,不需要再根据字段在页面中的位置做判断。
返回的字段和本地 OCR 得到的文本都在识别层内部处理;重命名和导出流程只接收 InvoiceRecord。
后续逻辑因此不依赖某个 OCR 服务。换成腾讯云、PaddleOCR 或公司内部接口时,只需增加对应的识别实现,文件命名、Excel 导出和 Web 页面可以继续使用。

为了能够适应各种不同的应用场景,这个工具的是提供了云端和本地两种识别方式,两者共用后续整理流程。
云端模式会根据文件类型,把图片、PDF 或 OFD 发送到百度的增值税发票识别接口,然后从 words_result 中提取字段。它对扫描件、截图和不同版式的适应性更好,也能直接处理 OFD。
RapidOCR 是一个可以在本机运行的 OCR 工具,脚本通过 ONNX Runtime 执行识别模型。它返回文字及其位置,但不会直接给出“开票日期”或“价税合计”这类发票字段。因此,本地方案还需要把 PDF 页面渲染成图片,并用规则从识别文本中提取所需字段。
本地模式则采用分层策略:
如果关键字段不完整,再用 PyMuPDF 把页面渲染成图片,交给 RapidOCR。两条路径最终都会得到同一种记录,后面的流程完全一致:
识别方式与文件整理规则由此保持独立。
识别出字段以后,脚本使用下面的格式生成文件名:
例如:
2026-08-13+358.00+25132000000012345678.pdf
生成文件名时,程序会统一日期格式、清理非法字符、填充缺失字段,并为同名文件追加序号。
命名逻辑集中在一个函数中,相同记录会生成相同的基础文件名。修改规则时不需要改动识别代码。
其他文档也可以定义自己的命名规则。例如合同可以使用签署日期+客户+合同编号,银行回单可以使用“交易日期+金额+对方名称”。
完整安装步骤放在随项目提供的 README.md 中。基本命令如下:
uv venv --python 3.12uv pip install -r requirements.txt.venv/bin/python invoice_organizer.py
Windows 使用 .venv\Scripts\python.exe invoice_organizer.py。
有了这个工具之后,是不是觉得整理发票这件事变得简单了许多。虽然目前它还有一些很明显的缺陷,例如:百度接口只读取 PDF 和 OFD 的第一页;本地识别遇到低清扫描件或特殊版式时,字段可能不完整;同名文件虽然不会被覆盖,但程序还不能判断两张发票是否重复。
当然,这个工具未必需要一次做得很大,先解决手边最重复的工作,再根据实际使用慢慢补齐就够了。
如果你也有类似的整理工作,可以从自己的文件夹里挑几份样本,看看哪些信息值得提取,平时又是按照什么规则命名和归档。把这些习惯写成代码,往往就能得到一个更贴合自己工作的工具。也欢迎你在这个版本上继续尝试,做出自己的改法。
源码及文档下载地址: https://pan.baidu.com/s/1yRBeSXoRAi0AlOSLzVj8cg?pwd=h28k