PDF批量发票信息提取工具(有源码)

查看 56|回复 10
作者:pythonfun   
一、软件名称:PDF批量发票信息提取工具
本软件主要解决职场人士报销填表录入时速度慢、易出错的痛点。参考了网上现有代码,并进行了一定的修改和完善,兼容当下主流量的两种发票格式。执行速度快,效率高,准确性大大提升。
二、软件功能:
本软件是一款专门用于批量提取PDF发票关键信息的工具,主要功能包括:
1. 支持批量扫描指定文件夹中的PDF发票文件,自动过滤非发票文件
2. 提取发票的核心信息,包括:发票代码、发票号码、开票日期、校验码、公司名称、金额和税额
3. 自动处理文本格式,去除多余空格或符号,确保数据整洁
4. 将提取的信息实时写入Excel表格,方便后续统计与管理
5. 异常处理机制完善,遇到无法读取的PDF文件时,会记录错误并继续处理其他文件
三、使用方法:
把软件或代码放到发票文件夹,再运行,默认执行当前目录(不包括子目录)所有pdf文件
1. 运行程序后,软件将在当前目录下扫描所有PDF文件并提取发票信息:
2. 将需要处理的PDF发票文件放入同一文件夹(程序当前工作目录)
3. 运行程序,程序会自动识别文件夹内的PDF文件并解析第一页内容
4. 提取成功的信息会显示在控制台,同时写入名为 “发票信息.xls” 的Excel文件
5. Excel表格中会按行记录每张发票的详细信息,列名依次为:发票代码、发票号码、开票日期、校验码、公司、金额、税额
6. 遇到无法读取的文件,程序会在控制台输出错误信息,保证其他文件正常处理
四、运行环境:
Python 3.x, 依赖库安装命令:
pip install pdfplumber xlwt
运行方式:在cmd命令行中执行脚本即可
五、特点亮点:
1. 无需图形界面,轻量化,适合批量处理
2. 自动正则匹配发票关键字段,减少人工操作
3. 输出Excel文件格式统一,便于二次处理和统计
六、输出结果:


image.png (72.86 KB, 下载次数: 1)
下载附件
2025-10-27 08:05 上传

七、下载地址:
https://pan.baidu.com/s/1911W7uJZHvZomVeF_atT-A?pwd=zr4w 提取码: zr4w
八、源码展示:
[Python] 纯文本查看 复制代码import pdfplumber
import re
import os
import xlwt
# 创建工作簿
wb = xlwt.Workbook()
# 创建表单
sh = wb.add_sheet('sheet 1')
for i, name in zip(range(7), ['发票代码', '发票号码', '开票日期', "校验码", '公司', '金额', '税额']):
    sh.write(0, i, name)
def re_text(bt, text):
    m1 = re.search(bt, text)
    if m1:
        return re_block(m1.group(1))
    return ""
def re_block(text):
    return re.sub(r"[ )):]", "", text)
def read():
    filenames = [file.name for file in os.scandir(".") if file.name.endswith(".pdf")]
    row = 1
    for filename in filenames:
        if not filename.lower().endswith('.pdf') or filename.startswith('~$'):
            continue
        try:
            with pdfplumber.open(filename) as pdf:
                first_page = pdf.pages[0]
                pdf_text = first_page.extract_text()
                if '发票' not in pdf_text:
                    continue
                # 获取发票信息
                fapiaodaima = re_text(r'发票代码(.*\d+)', pdf_text)
                fapiaohaoma = re_text(r'发票号码(.*\d+)', pdf_text)
                kaipiaoriqi = re_text(r'开票日期(.*)', pdf_text)
                jiaoyan = re_text(r'校 验 码\s*[::]\s*([a-zA-Z0-9 ]+)', pdf_text)
               
                # 处理金额和税额的提取
                heji_match = re_text(r'合 计(.*)', pdf_text)
                heji = re.split(r"¥|¥", heji_match) if heji_match else ["", ""]
                jine = heji[1] if len(heji) > 1 else ""
                shuie = heji[2] if len(heji) > 2 else ""
               
                # 提取公司名称
                company_match = re.findall(r'名.*?称\s*[::]\s*([一-龟]+)', pdf_text)
                gongsi = re_block(company_match[-1]) if company_match else ""
                lst=[fapiaodaima,fapiaohaoma,kaipiaoriqi,jiaoyan,gongsi,jine,shuie]
                print(lst)
               
                # 写入Excel
                for i, value in enumerate(lst):
                    sh.write(row, i, value)
                row += 1
        except Exception as exc:
            print(f"Error processing {filename}: {exc}")
# 保存Excel
read()
wb.save('发票信息.xls')

发票, 文件

Kls673M   

感谢分享, 我这边测试发现获取的表达式是固定的,会出现有时获取不准确的情况,建议做外置配置文件或者使用其他方式进行获取信息
[Asm] 纯文本查看 复制代码   with pdfplumber.open(file_path) as pdf:
        text_content = ""  # 用于存储整个PDF的文本内容
        for page in pdf.pages:
            text = page.extract_text()
            if not text:
                print("无法提取文本内容,跳过当前页面")
                continue
            text_content += text + "\n"  # 累加每页的文本内容
            # 提取发票号码
            if '发票号码' not in invoice_info:
                for pattern in invoice_number_patterns:
                    number_match = re.search(pattern, text, re.IGNORECASE)
                    if number_match:
                        invoice_number = number_match.group(1).strip()
                        print("-----------------------------------------------")
                        invoice_info['发票号码'] = invoice_number
                        print(f"提取到发票号码: {invoice_number}")
                        break
            # 提取销售方名称
            if '销售方名称' not in invoice_info:
                for pattern in sales_name_patterns:
                    match = re.search(pattern, text, re.IGNORECASE)
                    if match:
                        sales_name = match.group(1).strip()
                        invoice_info['销售方名称'] = sales_name
                        print(f"提取到销售方名称: {sales_name}")
                        break
            # 提取小写金额
            if '小写金额' not in invoice_info:
                for pattern in amount_patterns:
                    amount_match = re.search(pattern, text, re.IGNORECASE)
                    if amount_match:
                        amount_section = amount_match.group(1).strip()
                        invoice_info['小写金额'] = amount_section
                        print(f"提取到小写金额: {amount_section}")
                        break
            # 如果已经提取到所有必要信息,提前退出循环
            if '销售方名称' in invoice_info and '发票号码' in invoice_info and '小写金额' in invoice_info:
                break
sales_name_patterns =
    销 名称:(.*?)\n
    销 名 称 :(.*?)\n
    售 名称:(.*?)\n
amount_patterns =
    (小写)¥(\d+\.\d+)
    (小写) ¥(\d+\.\d+)\n
    ( 小 写 ) ¥(\d+\.\d+)\n
    ( 小写)¥(\d+\.\d+)\n
invoice_number_patterns =
    发票号码:(\d+)
    发票 号码:(\d+)
    发票 号码: (\d+)
    发票号码: (\d+)
    发票号 码 : (\d+)
    发 票 号 码 : (\d+)
    发 票 号 码 :(\d+)
    发票号 码 :(\d+)
winnie989   

C:\Users\admin\PycharmProjects\456\.venv\Scripts\python.exe C:\Users\admin\PycharmProjects\456\PDF发票提取.py
Traceback (most recent call last):
  File "C:\Users\admin\PycharmProjects\456\PDF发票提取.py", line 1, in
    import pdfplumber
ModuleNotFoundError: No module named 'pdfplumber'   
  运行了 pip install pdfplumber xlwt   还是提示这个
pythonfun
OP
  

下载地址里有打包成exe,同时附py代码。
zzs_70   

不错,支持原创
cuimen   

不错,不错,感谢楼主
tooo   

谢谢分享,下载试试效果如何。
bachelor66   

搞个条码枪扫二维码的也不错                             
abCdeU   

感谢分享楼主万福
afaty   


bachelor66 发表于 2025-10-27 08:42
搞个条码枪扫二维码的也不错

非常同意这个看法
您需要登录后才可以回帖 登录 | 立即注册

返回顶部