起因
帮朋友处理公司发票报销时发现一个痛点:每个月几十上百张电子发票,财务需要一张张打开、复制发票号码、金额、税额、购买方名称……手工录入 Excel,眼睛看花,手指抽筋。
市面上的发票识别工具要么收费,要么必须联网上传(谁敢把公司发票数据传到第三方服务器?),要么只支持 PDF 不支持 OFD 和图片。所以决定自己写一个。
成品
增值税发票批量提取工具 —— 完全离线运行的 Windows 桌面软件,双击 exe 即用,不写注册表、不需要管理员权限、不联网。
能做什么
| 功能 | 说明 |
|---|---|
| PDF 电子发票 | 双引擎提取(文字层 + 表格层),3 级降级兜底 |
| OFD 电子发票 | 国标版式文档解析,双引擎(ofdparser + 原生 XML) |
| 纸质发票照片 | OCR 识别,自动灰度化 + 二值化 + 去噪 + 纠偏 |
| 23 字段提取 | 发票代码/号码/日期/购买方/销售方/税号/金额/税额/价税合计/税率/备注…… |
| 真伪初筛 | 5 项格式校验 + 税率合法性 + 金额数学验证 |
| 重复检测 | 同批次去重 + 历史数据库去重 + SHA256 文件哈希 |
| Excel 输出 | 双 sheet(明细 + 汇总),异常行红色高亮,重复行黄色标记 |
| 自动归档 | 按月份归类,文件按「日期_购买方_发票号码」重命名 |
| 数据库自愈 | SQLite 损坏自动检测并修复,异常关机不丢数据 |
| 配置三层兜底 | 硬编码默认值 → 资源文件 → 用户配置,坏了一个还有两个 |
两个版本
| 版本 | 体积 | 纸质发票 OCR | 适用人群 |
|---|---|---|---|
| 完整版 | ~240MB | ✅ 内置便携 OCR 引擎 | 财务公司、代理记账 |
| 轻量版 | 86MB | ❌ 仅 PDF/OFD | 纯电子发票用户 |
轻量版已经足够应对 90% 的场景 —— 现在几乎全是电子发票了。
技术栈
- GUI: Python tkinter,左右分栏布局,后台线程处理不卡界面
- PDF: PyMuPDF + pdfplumber 双引擎,扫描件降级到 OCR
- OFD: ofdparser + 原生 XML(含 XXE 防护)
- OCR: 便携式 Tesseract(不写注册表,不设环境变量,随 exe 分发)
- Excel: openpyxl,带样式(字体/颜色/列宽/冻结窗格),公式注入防护
- 数据库: SQLite + PRAGMA integrity_check 自愈
- 打包: PyInstaller --onedir --windowed,英文名构建避中文路径坑
设计原则
全程不可变数据模型(frozen dataclass),所有界面文案用会计大白话(不出现 "OCR" "Tesseract" "pymupdf" 等技术名词),异常绝不崩溃(每个模块都有降级路径)。
测试
323 个 pytest 用例,14 大类覆盖:模型层、工具层、提取器、验证链、数据库、Excel 输出、GUI 冒烟。全部通过。
开源
代码在 GitHub,欢迎提 issue 和 PR。
后续计划
- TK 小窗闪现问题(纯视觉瑕疵)
- 拖拽添加文件支持
- 更多发票类型(机动车发票、通行费发票)
- macOS 适配(目前仅 Windows)
🤖 本文由 Claude Code 辅助撰写,项目代码由 Claude Code 辅助开发。