

发票识别总出错?这 5 个坑我帮你踩完了
大家好,我是正在实战各种 AI 项目的程序员晚枫。
😭 我踩过的那些坑
3 个月前:
刚开始做发票自动识别项目。
信心满满:不就是调用个 API 吗?能有多难?
现实打脸:
- 密钥失效,代码跑不起来
- 图片模糊,识别一塌糊涂
- 网络超时,程序直接崩溃
- Excel 格式不对,财务姐姐骂我
- 密钥泄露,腾讯云账号被盗用
那段时间:
- 每天都在修 bug
- 财务每天都在抱怨
- 老板每天都在问进度
- 我每天都在怀疑人生
但现在:
所有坑都填平了,项目稳定运行 3 个月。
今天:把这 5 个坑分享给你,帮你避雷。
🕳️ 坑 1:密钥泄露(最危险)
问题描述
我做的:
1 2 3 4 5 6 7 8 9 10
| SECRET_ID = 'AKIDxxxxxxxx' SECRET_KEY = 'xxxxxxxxxxxxxxxx'
poocr.ocr2excel.VatInvoiceOCR2Excel( input_path='./invoices', output_path='./output', id=SECRET_ID, key=SECRET_KEY )
|
然后:我把代码传到了 GitHub。
后果:
- 第 2 天,收到腾讯云短信:您的账户产生异常消费
- 查账单:被盗用,产生了 2000 多元费用
- 找客服:密钥已泄露,只能冻结账户
损失:
- 金钱:2000 多元(腾讯云赔付了大部分)
- 时间:折腾 3 天
- 心情:崩溃
正确做法
用环境变量:
1 2 3 4 5 6 7 8 9 10 11 12
| import os
SECRET_ID = os.getenv('TENCENT_SECRET_ID') SECRET_KEY = os.getenv('TENCENT_SECRET_KEY')
poocr.ocr2excel.VatInvoiceOCR2Excel( input_path='./invoices', output_path='./output', id=SECRET_ID, key=SECRET_KEY )
|
配置环境变量(Windows):
1 2
| setx TENCENT_SECRET_ID "你的 SecretId" setx TENCENT_SECRET_KEY "你的 SecretKey"
|
或者用配置文件:
1 2 3 4 5 6
| SECRET_ID = 'AKIDxxxxxxxx' SECRET_KEY = 'xxxxxxxxxxxxxxxx'
config.py
|
记住:
- 密钥不要硬编码
- 不要上传到 GitHub
- 定期更换密钥
- 发现泄露立即冻结
🕳️ 坑 2:图片质量差(最常见)
问题描述
财务姐姐交来的发票:
- 手机拍的,手抖,模糊
- 光线暗,看不清
- 有反光,字被挡住
- 折叠的,有褶皱
- 斜着拍的,变形
识别结果:
- 发票号码识别错误
- 金额识别错误
- 日期识别错误
- 干脆识别失败
财务姐姐说:"你这什么破工具,还不如我手录!"
正确做法
制定发票提交规范:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 📋 发票提交规范
1. 优先使用电子版 PDF 发票 2. 拍照发票要求: - 光线充足 - 发票平整 - 无反光 - 正对拍摄 - 四角完整 3. 推荐使用扫描 APP: - 扫描全能王 - 微软 Lens - Adobe Scan 4. 不要折叠、不要揉搓
|
添加质量检查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import cv2
def check_image_quality(image_path): """检查图片质量""" img = cv2.imread(image_path) brightness = np.mean(img) if brightness < 50: return False, "图片太暗" gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) variance = cv2.Laplacian(gray, cv2.CV_64F).var() if variance < 100: return False, "图片模糊" return True, "合格"
is_ok, msg = check_image_quality('invoice.jpg') if not is_ok: print(f"❌ {msg},请重新拍照")
|
效果:
- 识别准确率从 95% → 98%+
- 财务姐姐不骂了
- 我也不崩溃了
🕳️ 坑 3:网络超时(最烦人)
问题描述
公司内网环境:
程序表现:
1 2 3 4 5
| 正在识别发票... [超时] 请求失败 [超时] 请求失败 [超时] 请求失败 程序崩溃
|
财务姐姐:"怎么又失败了?"
我:"网络问题……"
财务姐姐:"我不管,今天必须弄好!"
正确做法
添加重试机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import time from requests.exceptions import Timeout, ConnectionError
def recognize_with_retry(input_path, output_path, max_retries=3): """带重试的识别函数""" for i in range(max_retries): try: poocr.ocr2excel.VatInvoiceOCR2Excel( input_path=input_path, output_path=output_path, id=SECRET_ID, key=SECRET_KEY ) print("✅ 识别成功") return True except (Timeout, ConnectionError) as e: print(f"⚠️ 第{i+1}次失败:{e}") if i < max_retries - 1: print("⏳ 5 秒后重试...") time.sleep(5) else: print("❌ 重试失败,请检查网络") return False
recognize_with_retry('./invoices', './output')
|
批量处理时分小批次:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| poocr.ocr2excel.VatInvoiceOCR2Excel( input_path='./1000_invoices', ... )
for i in range(10): batch_path = f'./batch_{i}' poocr.ocr2excel.VatInvoiceOCR2Excel( input_path=batch_path, ... ) print(f"✅ 第{i+1}批完成")
|
添加超时设置:
1 2 3 4
| import poocr
poocr.config.timeout = 30
|
效果:
🕳️ 坑 4:Excel 格式不对(最尴尬)
问题描述
我生成的 Excel:
| 发票代码 | 发票号码 | 金额 | 税额 | 日期 |
|---|
| 011002100113 | 12345678 | 1000 | 130 | 2026-03-15 |
财务姐姐要的:
| 发票代码 | 发票号码 | 开票日期 | 不含税金额 | 税额 | 价税合计 | 备注 |
|---|
| 011002100113 | 12345678 | 2026 年 03 月 15 日 | 1,000.00 | 130.00 | 1,130.00 | |
财务姐姐:"这格式不对啊,我还要手动调整?"
我:"……我改。"
正确做法
自定义输出模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import pandas as pd from datetime import datetime
def format_invoice_excel(raw_data, output_path): """格式化 Excel 输出""" df = pd.read_excel(raw_data) df.rename(columns={ '金额': '不含税金额', '日期': '开票日期' }, inplace=True) df['价税合计'] = df['不含税金额'] + df['税额'] df['开票日期'] = df['开票日期'].apply( lambda x: datetime.strftime(x, '%Y年%m月%d日') ) for col in ['不含税金额', '税额', '价税合计']: df[col] = df[col].apply(lambda x: f"{x:.2f}") df['备注'] = '' df = df[['发票代码', '发票号码', '开票日期', '不含税金额', '税额', '价税合计', '备注']] df.to_excel(output_path, index=False) print(f"✅ 格式化完成:{output_path}")
format_invoice_excel('./raw_data.xlsx', './output/发票识别结果.xlsx')
|
提前沟通格式:
1 2 3 4 5 6 7 8
| format_requirements = """ 请确认 Excel 格式要求: 1. 列名:发票代码、发票号码、开票日期、不含税金额、税额、价税合计、备注 2. 日期格式:YYYY 年 MM 月 DD 日 3. 金额格式:保留 2 位小数,带千分位 4. 其他要求:_______ """
|
效果:
- Excel 格式符合要求
- 财务姐姐直接能用
- 我不尴尬了
🕳️ 坑 5:异常发票处理(最容易忽略)
问题描述
98% 的发票:识别成功,没问题。
2% 的发票:
- 太模糊,识别失败
- 发票类型特殊,不支持
- 发票损坏,无法读取
- 重复发票,需要标记
我之前没处理:
- 失败的发票没记录
- 不知道哪些需要手动处理
- 财务姐姐问:"这 5 张呢?"
- 我:"……我找找。"
正确做法
添加异常记录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import json from datetime import datetime
def process_invoices_with_log(input_path, output_path): """处理发票并记录异常""" failed_invoices = [] for invoice_file in os.listdir(input_path): try: poocr.ocr2excel.VatInvoiceOCR2Excel( input_path=os.path.join(input_path, invoice_file), output_path=output_path, id=SECRET_ID, key=SECRET_KEY ) print(f"✅ {invoice_file} 识别成功") except Exception as e: print(f"❌ {invoice_file} 识别失败:{e}") failed_invoices.append({ 'filename': invoice_file, 'error': str(e), 'time': datetime.now().isoformat() }) if failed_invoices: with open('./failed_invoices.json', 'w', encoding='utf-8') as f: json.dump(failed_invoices, f, ensure_ascii=False, indent=2) print(f"⚠️ 有{len(failed_invoices)}张发票识别失败,详见 failed_invoices.json") else: print("✅ 所有发票识别成功")
process_invoices_with_log('./invoices', './output')
|
生成异常报告:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| def generate_failed_report(failed_list, output_path): """生成异常发票报告""" report = "# 发票识别失败报告\n\n" report += f"生成时间:{datetime.now()}\n\n" report += f"失败数量:{len(failed_list)}\n\n" report += "## 失败清单\n\n" report += "| 文件名 | 错误原因 | 建议 |\n" report += "|--------|----------|------|\n" for item in failed_list: suggestion = "重新拍照" if "模糊" in item['error'] else "手动处理" report += f"| {item['filename']} | {item['error']} | {suggestion} |\n" with open(output_path, 'w', encoding='utf-8') as f: f.write(report) print(f"📋 异常报告已生成:{output_path}")
|
效果:
- 异常发票有记录
- 财务姐姐知道哪些需要手动处理
- 责任清晰,不扯皮
📊 避坑检查清单
部署前检查:
全部打勾,再上线。
💬 联系我
主营业务:AI 编程培训、企业内训、技术咨询
🎓 推荐课程
坑,我帮你踩完了。
路,我给你铺平了。
现在,轮到你了。
行动起来,让发票识别不再痛苦。 💪
P.S. 财务姐姐上周给我送了杯奶茶,说:"小枫啊,现在这工具真好用,不骂你了。"
我:"……谢谢姐姐。"
这杯奶茶,真甜。
🎓 AI 编程实战课程
想系统学习 AI 编程?程序员晚枫的 AI 编程实战课 帮你从零上手!