奇观报销 · 大众版使用指南
> 一句话:你月初按一下回车,发票的"归集 → 识别 → 填表 → 发送 → 存档"就全自动跑完,月底再也不用手工一张张贴发票。
本指南是给普通用户看的:不讲内部实现,只讲"它能干什么、你怎么用、出问题怎么办"。如果你就是想少加班、把报销这事交给机器,看这一篇就够了。
一、它能替你做什么(大白话)
| 你原来要做的 | 现在机器做的 |
|---|---|
| 一封封翻邮箱,把发票下载下来 | 自动去邮箱把发票收回来(PDF / OFD / XML 都认,不用你登录任何发票平台) |
| 眯着眼核发票上的金额、税号 | 把金额、买卖方、税号读出来,金额优先保证准确 |
| 凭感觉分"交通/招待/办公" | 自动归类(交通费 / 交际费 / 办公费 …) |
| 在 Excel 里一行行手抄 | 自动填好制式报销单(两种版式都给) |
| 压缩发票、发邮件给自己 | 自动打包并发送一封邮件到你邮箱 |
| 事后担心被人改过 | 每张带黄金指纹,可随时核对、防篡改 |
整套流程不需要你登录任何发票网站、不需要任何外部 OCR 付费服务——它尽量"自己把自己搞定"。
二、你最终会收到什么(1 封邮件 · 4 个附件)
跑完之后,你的邮箱会收到一封报销单邮件,里面挂着 4 个附件:
| # | 附件 | 是什么 | 用处 |
|---|---|---|---|
| 1 | qiiyoo-202606-报销单-逐笔填写-5,280.00.xlsx |
逐张填写版报销单 | 每张发票占一行,金额直接是数字,最直观 |
| 2 | qiiyoo-202606-报销单-合并填写-5,280.00.xlsx |
合并填写版报销单 | 同一客户合并成一行,金额格写"求和公式"(见第五节) |
| 3 | qiiyoo-张三-报销单数据库-202606-28行.xlsx |
报销单数据库 | 全部发票的结构化清单,方便筛选/统计 |
| 4 | qiiyoo-电子发票-202606-28张.zip |
电子发票包 | 当期所有发票原件(PDF/OFD)打包,留档用 |
> 文件名里的 202606 是报销期、28行/28张 是发票数量、5,280.00 是合计金额——扫一眼就知道这封邮件对不对。
三、三步上手(真的只要三步)
第 1 步:装依赖(一次性)
pip install PyMuPDF openpyxl requests beautifulsoup4 numpy pillow onnxruntime
> 扫描件发票的 OCR 引擎(PP-OCRv4)代码已自带,权重首次运行自动联网下载(约 16MB),不用你提前准备模型,也不用装 tesseract / poppler。
第 2 步:填配置(一份 config.json)
复制 config.example.json 为 config.json,把这几项填成你自己的:
| 字段 | 填什么 | 例子 |
|---|---|---|
company.name |
你公司全称 | 示例科技有限公司 |
company.short_name |
公司简称(进文件名) | 示例 |
company.department |
部门 | 总经理室 |
user.name |
你的名字 | 张三 |
user.phone |
手机号 | 填了才能处理"扫码开发票"的表单类发票 |
period |
报销期(年+月) | 202606 |
email.host / port |
邮箱 SMTP | smtp.qq.com / 465 |
email.user |
发件邮箱 | 你的邮箱@qq.com |
email.password |
邮箱授权码(不是登录密码) | 在邮箱设置里生成 |
email.to |
收件人(通常就是你自己) | 你的邮箱@qq.com |
paths.logo_image |
你的 Logo 图片(可选) | 留空则用内置默认 Logo |
两个授权码要分清:
- 采集用(去邮箱读发票):通过环境变量 YS_IMAP_PASS 传入;
- 发送用(把报销单发给你):填在 config.json 的 email.password。
export YS_IMAP_PASS='你的邮箱授权码'
第 3 步:跑两条命令(漩涡 Vortex → 龙卷风 Tornado)
# ①【漩涡 Vortex·采集】从邮箱下载并识别本期发票
python3 run.py
# ②【龙卷风 Tornado·填报发送】生成报销单 + 发送邮件(一条命令一步到位)
python3 send_report_public.py --send -c config.json
完事。打开邮箱,报销单已经在里面了。
> 两条命令对应奇观内部两条流水线:漩涡 Vortex(采集·下载·识别) 负责把发票收回来并识别入库;龙卷风 Tornado(填报·发送) 负责填表、打包、发送。你只需按顺序点两下。
四、命令详解(按需取用)
| 命令 | 作用 |
|---|---|
python3 run.py |
采集:读邮箱、下载发票、识别金额与分类、入库。无参数,只读环境变量。 |
python3 send_report_public.py --send -c config.json |
生成 + 发送:产出双版本报销单、数据库、发票包,并发送邮件。 |
python3 send_report_public.py -c config.json |
只预览不发送:生成 .eml 预览文件,核对无误再加 --send 真发。 |
python3 main.py -c config.json |
只生成不发送(高级):单独生成报销单与发票包,不发邮件。 |
> 想重发某个月?把 config.json 里的 period 改成那个月(如 202604),重跑第 ③ 步即可。
五、核心能力通俗讲(为什么它靠谱)
1. 免登录采集,绝不"因噎废食"
所有发票下载都不需要登录任何平台;遇到"要点登录才能下"的链接,它只跳过那一条链接,不会把整封邮件丢掉——该下的发票照下。
2. 同一张发票多种格式?用 OFD,最稳
一张发票常常同时有 PDF 和 OFD。系统会优先用 OFD(不依赖任何外部库、又是同一张票的权威格式)来提取信息,并和 PDF 互相交叉验证;只有都没有 OFD/XML 时才退而求其次用 PDF。这样既不重复下载,又能互相兜底。
3. 金额优先保证准确(这是底线)
发票上"中文大写金额行紧跟 ¥"才是真·价税合计(如 伍拾肆圆肆角整 / ¥54.40),系统以它为金标准;再用"不含税 + 税额 ≈ 价税合计"做三联校验,对不上就降级记录、绝不瞎猜。
4. 自动分类,全链路一个标准
采集端和报表端用同一套分类规则,所以数据库、导出 JSON、最终报销单的分类永远不会"对不上"。眼镜/光学类发票会自动归到"办公费·礼品·宣传费广告费"。
5. 四附件规范
一封邮件挂 4 个附件(逐张版 / 合并版 / 数据库 / 发票包),符合规范的报销归档要求。
6. 合并金额"看得见"的公式
合并填写版里,金额格写的是求和公式(如 =22.00+5.00+12.50),既保留"由哪些发票相加而来"的审计痕迹,又保证用任何软件打开都能直接看到金额(部分阅读器不自动重算,系统会预先写入计算结果)。
7. 批注用"发票后8位|金额"
合并单元格的批注会写明每张发票的"发票号后八位|金额"(半角竖线分隔),一眼能对回原票。
8. 黄金指纹,防篡改可追溯
每张报销单带唯一指纹串(如 GF·a1b2…),发送后还能回看比对,事后谁改过一眼可见。
9. 处理留痕,异常不静默
每一步处理都有记录,个别发票下载失败、链接失效或扫码过期等情况会明确留痕并提示,不会悄悄吞掉——你随时知道哪些没处理、为什么。
六、常见问题(FAQ)
Q1:邮箱里没收到报销单邮件?
先核对 email.to 是不是填对了;再确认 email.password 是授权码而非登录密码;run.py 采集时 YS_IMAP_PASS 也要设。发送失败的明细会打印在终端。
Q2:有张发票没出现在报销单里?
常见三种:① 那条下载链接需要登录,按规则被跳过(不影响其他发票);② 是死链(平台已删除,系统记下来下次直接跳过);③ 是扫码开发票且已过期(二维码通常有效期数天~1 个月)。这类情况系统会留痕,不会静默吞掉。
Q3:金额看起来不对?
系统对"疑似但不能确定"的金额(如退款/红冲/差额)不会擅自改,只在备注里告警,交给你人工确认——这是故意的稳妥设计。
Q4:我想用自己的公司 Logo / 制式模板?
可以。paths.logo_image 填你的 Logo 图片即可;制式模板也能替换。系统内置了默认模板和默认 Logo,你换了自己的之后,默认的仍然保留、随时能回归,不会被覆盖丢失。
Q5:想先看看效果再发?
去掉 --send:python3 send_report_public.py -c config.json,会生成 .eml 预览文件,核对无误再加 --send 真发。
Q6:扫描件(照片/图片发票)能识别吗?
能。系统自带离线 OCR(PP-OCRv4,权重首次运行自动下载),不依赖任何外部 OCR 云服务;OCR 引擎万一不可用也会优雅降级,不影响电子发票主流程。
七、它为什么"稳、省心"(设计原则)
- 尽量自包含、少依赖:电子发票走文本层零误差读取;扫描件走自带离线 OCR;不绑任何云 OCR、不绑 tesseract/poppler。
- 金额零误差优先:大写金标准 + 三联校验,疑点降级记录,绝不静默误抽。
- 降级容错:各引擎都做了异常兜底,单个环节出问题不会拖垮全流程。
- 必要即全要素:只带跑通全流程必需的代码与资产,不塞冗余数据。
八、时间与预期(为什么是"10 分钟搞定")
设计目标,也是实测结果:你点一下,10 分钟以内拿到结果。 奇观把报销里最磨人的机械活——翻邮箱、下附件、识别发票——全部交给自动化,你的主动参与压缩到"运行一次 / 看一眼结果"。
真实耗时(机器在后台跑,你不用守着):
| 阶段 | 机器耗时(后台) | 你的精力 |
|---|---|---|
| 首跑 | 通常也约 10 分钟;仅当首次需下载离线 OCR 权重(约 16MB)或历史邮件极多时可能略长,但原实现实测很少超过 10 分钟 | 点一下就走,回来收结果 |
| 之后每次(增量) | 更快,几分钟级:只扫新到的邮件,迟到发票下月自动补 | 几乎无感 |
月度常态化报销极省时:从第二个月起,系统记住上次扫到哪(增量游标),只处理新发票;常规月度几十张发票,后台几分钟跑完,你只在月初"看一眼"邮件即可。
前提:只要严谨使用我们的代码、配置与环境不出错,每次基本都稳定在 10 分钟左右——慢,几乎都来自"用错 / 没配好",而不是程序本身。
透明耗时报告:每次运行结束会打印一张分段计时表(按方法 × 耗时、最慢的几封邮件和链接及其原因),让你清楚"慢在哪"——是平台发票页的浏览器下载慢,还是网络慢。设 YS_QUIET=1 可安静运行。
九、外部网络访问说明(透明告知)
工具只在你发起采集时访问邮件里发票签发平台的域名,用于下载发票本身,不外发任何与发票无关的个人信息:
fpj.datarj.com/invoice.datarj.com:下载停车费等「开票通」发票(等同你点开邮件里的链接,仅用链接自带的一次性访问令牌,不含金额/买方信息)。nnfp.jss.com.cn(诺诺)、wosai/sumpay/aliyuncs/oss-:下载各平台发票直链。
全部强制 HTTPS + 证书校验(已弃用明文 http:// 与 verify=False);内置离线 OCR,发票识别不上传任何云识别服务。若你完全不想让工具主动发外部请求,在 .env 设 YS_DISABLE_EXTERNAL_API=1,相关发票改由浏览器方式下载(与手动点击链接一致)。
> 一句话:自动化、非人工干预,只为省你的时间。每次约 10 分钟,月度报销更短。
> 奇观报销 · 自动化报销流水线
> 装好依赖、填好配置、两条命令,月底报销自动完成。