影刀RPA 发票自动识别与信息提取:OCR解放财务双手
作者:林焱
财务和行政经常需要从发票图片里提取:发票号码、金额、日期、开票方等信息。手动录入费时费力还容易出错。这篇讲用影刀+OCR自动识别发票信息。
方案对比
| 方案 | 准确率 | 速度 | 费用 |
|---|---|---|---|
| 百度OCR API | 高(专门优化发票) | 快 | 每天500次免费 |
| 腾讯OCR API | 高 | 快 | 每月1000次免费 |
| paddleocr(离线) | 中 | 较慢 | 免费 |
| pytesseract | 低 | 慢 | 免费 |
推荐百度OCR:专门有增值税发票识别接口,字段结构清晰,准确率高。
百度OCR发票识别
importrequestsimportbase64defrecognize_invoice(image_path):"""识别增值税发票"""# 1. 先获取access_tokenapi_key="你的API Key"secret_key="你的Secret Key"token_url=f"https://aip.baidubce.com/oauth/2.0/token"token_params={"grant_type":"client_credentials","client_id":api_key,"client_secret":secret_key}token_resp=requests.post(token_url,data=token_params)access_token=token_resp.json()["access_token"]# 2. 读取图片并Base64编码withopen(image_path,"rb")asf:image_base64=base64.b64encode(f.read()).decode()# 3. 调用发票识别接口ocr_url=f"https://aip.baidubce.com/rest/2.0/ocr/v1/vat_invoice"ocr_params={"access_token":access_token}ocr_data={"image":image_base64}resp=requests.post(ocr_url,params=ocr_params,data=ocr_data)result=resp.json()words=result.get("words_result",{})return{"发票号码":words.get("InvoiceNum",""),"发票代码":words.get("InvoiceCode",""),"开票日期":words.get("InvoiceDate",""),"金额":words.get("AmountInFiguers",""),"税额":words.get("TaxAmount",""),"价税合计":words.get("TotalAmount",""),"销售方名称":words.get("SellerName",""),"购买方名称":words.get("PurchaserName",""),}批量处理发票文件夹
importglobimportos invoice_dir="D:/发票/"results=[]forimg_fileinglob.glob(os.path.join(invoice_dir,"*.jpg"))+\ glob.glob(os.path.join(invoice_dir,"*.png"))+\ glob.glob(os.path.join(invoice_dir,"*.pdf")):try:info=recognize_invoice(img_file)info["文件名"]=os.path.basename(img_file)results.append(info)print(f"✓{img_file}:{info['发票号码']}¥{info['价税合计']}")exceptExceptionase:print(f"✗{img_file}:{e}")importtime time.sleep(0.5)# API频率限制# 写入Excelimportopenpyxl wb=openpyxl.Workbook()ws=wb.active headers=["文件名","发票号码","发票代码","开票日期","金额","税额","价税合计","销售方名称","购买方名称"]ws.append(headers)forrinresults:ws.append([r.get(h,"")forhinheaders])wb.save("发票识别结果.xlsx")踩坑实录
坑1:图片质量影响识别率
手机拍的发票照片如果有反光、模糊、倾斜,识别率会大幅下降。建议:
- 用扫描仪或高拍仪拍摄
- 图片分辨率不小于1024×768
- 尽量拍正,不要歪斜
坑2:Token过期
百度的access_token有效期30天。影刀长期运行时,token会过期。需要每次调用前检查或自动刷新:
importtime token_cache={"token":None,"expires_at":0}defget_token():iftime.time()<token_cache["expires_at"]:returntoken_cache["token"]# 重新获取resp=requests.post(token_url,data=token_params)data=resp.json()token_cache["token"]=data["access_token"]token_cache["expires_at"]=time.time()+data["expires_in"]-300returntoken_cache["token"]坑3:发票类型多样
百度OCR支持增值税专用发票、普通发票、电子发票等多种类型。但卷式发票、定额发票、出租车票等不支持。这些需要用通用OCR接口 + 自定义解析。
坑4:PDF发票要先转图片
百度OCR接口支持直接传PDF,但有大小限制(10MB)。超过大小的PDF需要先用Python的pdf2image库转为图片再识别。
离线索尼方案:paddleocr
如果数据敏感不想上传到百度(合规考虑),可以用paddleocr离线识别:
# pip install paddleocrfrompaddleocrimportPaddleOCR ocr=PaddleOCR(use_angle_cls=True,lang='ch')result=ocr.ocr(image_path,cls=True)# 提取所有文字texts=[]forlineinresult[0]:texts.append(line[1][0])# line[1][0]是识别出的文字# 手动解析:找关键字"发票号码"、"金额"等准确率不如百度,但完全离线、免费、数据不出本地。
写在最后
发票识别是每个财务人员的刚需。影刀+百度OCR,把原来人工几分钟一张的工作压缩到秒级,而且永远不会输错发票号码。一次搭好,终身受益。