用 OpenClaw 做「发票管家」:每月报销不再烦躁,AI 自动搞定一切
本文作者 qwk2009-39348 是阿里云天池”千模百炼”全球 AI 开发者系列锦标赛 —— OpenClaw 养虾挑战赛的参赛者。其用 OpenClaw 做了「发票管家」自动化系统,让每月报销“不再烦恼”。
报销有多烦,谁报谁知道。 发票满天飞、名字对不上、分类乱成一锅粥、月底对账对到怀疑人生……直到我用阿里云的轻量应用服务器的 OpenClaw 把这一切自动化了。
一、发票报销的痛苦,每个职场人都懂
每到月底,报销就成了噩梦:
-
邮件里全是发票附件 — 打开邮箱,发票 PDF 一个接一个,根本不知道哪些是新报销、哪些已经报过了;
-
重命名全靠手 — “发票_20240326_001.pdf”、”发票_V2_改.pdf”……改到最后自己都分不清哪个是哪个;
-
分类对账靠肉眼 — 办公费、交通费、餐饮费……一张张核对,眼睛都快瞎了;
-
月底汇总要命 — 几十张发票,Excel里一行行录,录到半夜还出错。
我就想问问:为什么赚钱不容易,报销却这么难?
于是,我用 OpenClaw 做了这个 ——「发票管家」自动化系统。
二、系统架构:四步走,自动化到飞起
┌─────────────────┐│ IMAP邮箱监控 ││ 自动抓取发票邮件│└────────┬────────┘│┌────────▼────────┐│ PDF内容解析 ││ 提取关键信息 │└────────┬────────┘│┌────────▼────────┐│ 自动重命名归档 ││日期+金额+类型 │└────────┬────────┘│┌────────▼────────┐│ 月底一键汇总 ││生成报销明细表 │└─────────────────┘
技术栈:
-
邮件监控:Python imaplib + 阿里云企业邮箱 IMAP
-
PDF 解析:PyPDF2 / pdfplumber
-
文件管理:Python shutil + os
-
表格生成:openpyxl
三、核心代码:手把手详解
步骤1:登录邮箱,搜索发票邮件
importimaplibimportemailfromemail.headerimportdecode_headerdefconnect_email():"""连接阿里云企业邮箱"""mail=imaplib.IMAP4_SSL('imap.qiye.aliyun.com',993)mail.login('noreply@qianwk.cn','your-password')mail.select('INBOX')returnmaildefsearch_invoice_emails(mail,days=30):"""搜索最近30天内的发票相关邮件"""# 搜索包含"发票"关键词的邮件status,messages=mail.search(None,'SUBJECT "发票" SINCE "-30d" UNSEEN')email_ids=messages[0].split()print(f'找到 {len(email_ids)} 封发票相关邮件')returnemail_ids
步骤2:下载并解析 PDF 发票内容
importpoplibimportosfromdatetimeimportdatetimedefdownload_invoice_attachment(mail,email_id,save_dir='/tmp/invoices'):"""下载发票附件"""os.makedirs(save_dir,exist_ok=True)status,msg_data=mail.fetch(email_id,'(RFC822)')raw_email=msg_data[0][1]msg=email.message_from_bytes(raw_email)forpartinmsg.walk():ifpart.get_content_type()=='application/pdf':filename=part.get_filename()iffilenameand'发票'in filename:filepath=os.path.join(save_dir,filename)withopen(filepath,'wb')as f:f.write(part.get_payload(decode=True))print(f'下载发票: {filename}')return filepathreturn None
步骤3:解析 PDF,提取发票关键信息
importpdfplumberdefparse_invoice_pdf(pdf_path):"""从PDF发票中提取关键信息"""withpdfplumber.open(pdf_path)as pdf:text=''for page in pdf.pages:text+=page.extract_text()or''# 用正则表达式提取关键字段info= {}# 发票号码match=re.search(r'发票号码[::]\s*(\d+)',text)if match:info['invoice_no']=match.group(1)# 开票日期match=re.search(r'(\d{4})年(\d{1,2})月(\d{1,2})日',text)if match:info['date']=f"{match.group(1)}-{match.group(2).zfill(2)}-{match.group(3).zfill(2)}"# 购买方名称match=re.search(r'购买方[::]\s*([^\n]+)',text)if match:info['buyer']=match.group(1).strip()# 销售方名称match=re.search(r'销售方[::]\s*([^\n]+)',text)if match:info['seller']=match.group(1).strip()# 价税合计金额match=re.search(r'价税合计[((]小写[))][::\s]*[¥¥]?\s*([\d.]+)',text)if match:info['total']=float(match.group(1))# 税率match=re.search(r'税率[::]\s*(\d+)%',text)if match:info['tax_rate']=int(match.group(1))# 项目名称match=re.search(r'项目名称[::]\s*([^*\n]+)',text)if match:info['item']=match.group(1).strip()returninfo
步骤4:自动重命名,按规则归档
importshutilfrompathlibimportPathdefrename_and_archive(invoice_info,pdf_path,archive_base='/tmp/invoices_archive'):"""根据发票信息自动重命名并归档命名规则:日期_金额_购买方_发票号码.pdf"""date=invoice_info.get('date','未知日期').replace('-','')total=int(invoice_info.get('total',0)*100) # 转为分,避免浮点buyer=invoice_info.get('buyer','未知')[:10] # 限制长度invoice_no=invoice_info.get('invoice_no','未知')[-8:]# 生成新文件名new_name=f"{date}_{total}_{buyer}_{invoice_no}.pdf"# 按年月分类归档year_month=date[:6]archive_dir=Path(archive_base)/year_montharchive_dir.mkdir(parents=True,exist_ok=True)dest_path=archive_dir/new_nameshutil.copy2(pdf_path,dest_path)print(f'归档完成: {new_name}')return dest_path
步骤5:月底一键生成报销汇总表
importopenpyxlfromopenpyxl.stylesimportFont,Alignment,PatternFillfromdatetimeimportdatetimedefgenerate_monthly_report(archive_base='/tmp/invoices_archive',year_m):"""生成月度报销汇总Excel表格"""archive_dir=Path(archive_base)/year_monthifnotarchive_dir.exists():print(f'目录不存在: {archive_dir}')returnwb = openpyxl.Workbook()ws = wb.activews.title = f'{year_month}报销明细'# 表头样式headers= ['序号', '日期', '发票号码', '购买方', '销售方', '项目', '金额', '税率', '税额', '价税合计']forcol,headerinenumerate(headers,1):cell=ws.cell(row=1,column=col,value=header)cell.font=Font(bold=True,color='FFFFFF')cell.fill=PatternFill(start_color='4CAF50',end_color='4CAF50',fill_type='solid')cell.alignment=Alignment(horiz)# 填充数据row=2total_amount=0forpdf_fileinsorted(archive_dir.glob('*.pdf')):info=parse_invoice_pdf(str(pdf_file))tax=round(info.get('total',0)*info.get('tax_rate',0)/100,2)total=info.get('total',0)+taxws.cell(row=row,column=1,value=row-1)ws.cell(row=row,column=2,value=info.get('date',''))ws.cell(row=row,column=3,value=info.get('invoice_no',''))ws.cell(row=row,column=4,value=info.get('buyer',''))ws.cell(row=row,column=5,value=info.get('seller',''))ws.cell(row=row,column=6,value=info.get('item',''))ws.cell(row=row,column=7,value=info.get('total',0))ws.cell(row=row,column=8,value=f"{info.get('tax_rate',0)}%")ws.cell(row=row,column=9,value=tax)ws.cell(row=row,column=10,value=total)total_amount+=totalrow+=1# 合计行ws.cell(row=row,column=1,value='合计')ws.cell(row=row,column=10,value=total_amount)ws.cell(row=row,column=10).font=Font(bold=True)# 设置金额格式forrinrange(2,row+1):forcolin [7, 9, 10]:ws.cell(row=r,column=col).number_format='¥#,##0.00'# 调整列宽ws.column_dimensions['A'].width=8ws.column_dimensions['B'].width=12ws.column_dimensions['C'].width=18ws.column_dimensions['D'].width=20ws.column_dimensions['E'].width=20ws.column_dimensions['F'].width=25ws.column_dimensions['G'].width=12ws.column_dimensions['H'].width=8ws.column_dimensions['I'].width=12ws.column_dimensions['J'].width=14output_path=f'{archive_base}/{year_month}_报销汇总.xlsx'wb.save(output_path)print(f'报销汇总表已生成: {output_path}')print(f'本月共 {row-2} 张发票,总金额:¥{total_amount:.2f}')returnoutput_path
四、运行效果
发票归档效果
/tmp/invoices_archive/├──202603/│ ├──20260324_19700_上海xxxxxx_8905066.pdf│ ├──20260324_21400_上海xxxxxx_1129182.pdf│ └──...
报销汇总表效果

五、核心价值:时间就是生命

六、进阶玩法
-
关键词过滤:只抓取特定主题的发票(如”项目报销”、”差旅费”)
-
微信推送:汇总表生成后自动推送到微信
-
OCR识别:对扫描件图片发票也支持识别
-
多邮箱支持:同时监控多个邮箱,统一汇总
报销本不该占用这么多时间。 用 OpenClaw 把繁琐的事交给 AI,你的时间应该用在更有价值的事情上。
技术栈:阿里云轻量应用服务器 OpenClaw + 阿里云企业邮箱 IMAP + Python PDF解析 + openpyxl


想要亲自上手搭建 Agent ?一键部署 Hermes & OpenClaw 传送门:
https://www.aliyun.com/activity/ecs/clawdbot
更多优秀作品场景化展示,将陆续发布,敬请期待。
夜雨聆风