吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 718|回复: 15
上一主题 下一主题
收起左侧

[原创工具] Python增值税发票识别+金额校验

[复制链接]
跳转到指定楼层
楼主
马马超超 发表于 2026-5-20 14:55 回帖奖励
本帖最后由 马马超超 于 2026-5-20 14:56 编辑

成品下载地址: 下载链接.txt (128 Bytes, 下载次数: 39)
帮朋友做一个发票内容识别的工具,最初选PaddleOCR,又使用EasyOCR,可能是我电脑性能不行,识别很慢,准确率还低的可怜!
后来琢磨了一段时间,感觉发票识别只不过是识别图片-->提取文字内容-->格式化文字内容-->输出表格!
开搞开搞:第一步,使用之前大神提取出的WX的ocr插件,把文字全部提取出来;第二步,通过re正则匹配,把所有想要的内容提取出来;第三步,使用pd把内容导出表格,顺道加了一个“税前+税额=总税值”的校验计算,速度很快,普通电脑几秒处理完几十张发票!

有一条出错信息:是因为发票为2页,第2页没有内容,校验失败,完全符合预期!

上源码:
[Python] 纯文本查看 复制代码
import re
import sys

import pandas as pd
import wcocr
#本地 wcocr.pyd文件
import os
wechat_path = os.getcwd() + r"\wxocr2"
wechatocr3_path = os.getcwd() + r"\wxocr2\WeChatOCR.exe"
# ==================== 核心:自动格式化发票 ====================
def format_invoice(ocr_result):
    # 过滤低置信度噪点文本
    valid_texts = []
    for item in ocr_result:
        txt = item.get("text", "").strip()
        score = item.get("rate", 0.0)
        if txt and score >= 0.5:
            valid_texts.append(txt)

    full_str = " ".join(valid_texts)
    res = {
        "发票号码": "",
        "不含税金额": "",
        "税额": "",
        "价税合计": "",
        "税率": "",
        "销售方信息": "",
        "开票日期": "",
        "发票类型": ""
    }

    # 1. 发票类型识别
    if "增值税专" in full_str and "用发票" in full_str:
        res["发票类型"] = "增值税专用发票"
    elif "电子发票" in full_str:
        res["发票类型"] = "增值税电子普通发票"
    elif "普通发票" in full_str:
        res["发票类型"] = "增值税普通发票"

    # 2. 发票号码
    num_reg = re.search(r"发票号码\s*[::]\s*(\d+)", full_str)
    if num_reg:
        res["发票号码"] = num_reg.group(1)

    # 3. 开票日期
    date_reg = re.search(r"开票日期\s*[::]\s*(\d{4}年\d{1,2}月\d{1,2}日)", full_str)
    if date_reg:
        res["开票日期"] = date_reg.group(1).replace("年", "-").replace("月", "-").replace("日", "")

    # 4. 税率 通用匹配 0%-17%
    rate_reg = re.search(r"(\d{1,2}\.?\d?)%", full_str)
    if rate_reg:
        res["税率"] = rate_reg.group(1) + "%"

    # 5. 提取所有金额数字(保留两位小数)必须带 ¥ 或者 ¥
    money_pat = re.compile(r"[¥¥]\s*(\d+\.\d{2})")
    all_money = money_pat.findall(full_str)
    # 去重
    money_list = list(set(all_money))
    #print(money_list)
    # 转浮点排序:小=税额 中=不含税 大=价税合计
    try:
        money_sort = sorted([float(m) for m in money_list])
        if len(money_sort) >= 3:
            res["税额"] = f"{money_sort[0]:.2f}"
            res["不含税金额"] = f"{money_sort[1]:.2f}"
            res["价税合计"] = f"{money_sort[2]:.2f}"
        elif len(money_sort) == 2:
            res["不含税金额"] = f"{money_sort[0]:.2f}"
            res["价税合计"] = f"{money_sort[1]:.2f}"
    except:
        pass
    #金额校准
    try:
        if float(res["税额"])+float(res["不含税金额"])==float(res["价税合计"]):
            res["金额校准"]="正确"
        else:
            res["金额校准"] = "出错"
    except:
        res["金额校准"] = "出错"

    # 6. 销售方信息整合
    #print(valid_texts)
    # #seller_keys = ["销售方", "纳税人识别号", "统一社会信用代码", "销售方地址", "开户行", "银行账号"]
    seller_keys = ["名称"]
    seller_data = []
    for text in valid_texts:
        if any(k in text for k in seller_keys):
            if len(text)>6:#防止识别到关键字,但是不是公司名
                seller_data.append(text)
    # 6. 销售方信息:只取 名称: 开头的销售方名称
    # 规则:两个名称,靠后出现的为销售方
    # 第二个名称为销售方
    #print(seller_data)
    if len(seller_data) >= 2:
        res["销售方信息"] = seller_data[1][3:].strip()
    elif len(seller_data) == 1:
        res["销售方信息"] = seller_data[0][3:].strip()
    #res["销售方信息"] = " | ".join(seller_data)
    return res


def get_all_jpg_files(folder_path):
    """
    遍历指定文件夹,返回所有 .jpg 文件的完整路径列表
    :param folder_path: 文件夹路径(如 "C:/发票/2025")
    :return: 所有 jpg 绝对路径列表
    """
    jpg_files = []

    # 遍历文件夹
    for filename in os.listdir(folder_path):
        # 只筛选 .jpg 文件(不区分大小写,也支持 .JPG)
        if filename.lower().endswith(".jpg"):
            full_path = os.path.join(folder_path, filename)
            jpg_files.append(full_path)

    return jpg_files
if __name__ == '__main__':
    #OUTPUT_EXCEL = "发票信息汇总表.xlsx"  # 输出表格名
    #if len(sys.argv) < 2:
    while 1:
        print("使用方法:")
        print("   输入发票文件夹路径即可")
        print("   当前只支持后缀为.jpg格式发票图片")
        print("示例:")
        print(r"  D:\发票\2026")
        # 命令行参数:只需要文件夹
        img_folder = input("发票路径:")
        if not os.path.isdir(img_folder):
            print(f"错误:文件夹不存在 → {img_folder}")
            continue

        # 开始处理
        print("开始批量处理发票...")
        exe_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
        OUTPUT_EXCEL = os.path.join(exe_dir, "发票信息汇总表.xlsx")
        #print(os.getcwd())
        tried_v3 = False
        if os.path.isfile(wechatocr3_path) and os.path.isdir(wechat_path):
            tried_v3 = True
            wcocr.init(wechatocr3_path, wechat_path)
        else:
            print("找不到微信3.x配置,或者不正确")
            continue
            # 1. 设置你的文件夹路径
        #target_folder = r"D:\python\Python+EasyOCR\png"  # 改成你自己的路径
        if tried_v3:
            # 2. 获取所有 jpg
            jpg_list = get_all_jpg_files(img_folder)

            # 3. 打印结果
            print(f"找到 {len(jpg_list)} 张 jpg 发票:")
            if len(jpg_list)>0:
                all_data = []
                for path in jpg_list:
                    print(path)
                    print("+"*30)
                    #jpgfile = input("输入图片文件名:")
                    result = wcocr.ocr(path)
                    #print(result)
                    #break
                    # 2. 自动格式化
                    invoice = format_invoice(result['ocr_response'])
                    # 3. 输出漂亮格式
                    invoice["图片路径"] = path  # 加入文件名方便核对
                    all_data.append(invoice)
                    # print("\n" + "=" * 50)
                    # print("          发票识别结果(格式化完成)")
                    # print("=" * 50)
                    # for key, value in invoice.items():
                    #     print(f"{key}:{value}")
                    # print("=" * 50)
                # 3. Pandas 输出Excel
                df = pd.DataFrame(all_data)
                df.to_excel(OUTPUT_EXCEL, index=False)

                print(f"\n&#9989; 提取完成!已保存到:{OUTPUT_EXCEL}")



免费评分

参与人数 5吾爱币 +11 热心值 +5 收起 理由
IcePlume + 1 + 1 我很赞同!
tail88 + 1 + 1 谢谢@Thanks!
ElEzUs + 1 + 1 我很赞同!
yulai3230 + 1 + 1 我很赞同!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
linglong2013 发表于 2026-5-20 18:24
思路很赞,可否有进一步的分析,比如领导想知道发票内容报销的趋势?比如季度年度大概哪些项目会发多少钱?大概意思就是你现在excel数据有了。如何让数据能说话和提供预测性趋势?不是柱形图,是AI给出业务建议。谢谢
推荐
hhbob23 发表于 2026-5-21 00:56
微信传过来的银行回单(jpg或png格式的)保存下来文件名称都变了,如何让文件名自动生成银行回单里的单位名称+金额这些信息呢。
沙发
yulai3230 发表于 2026-5-20 16:32
3#
zdnet 发表于 2026-5-20 16:41
yulai3230 发表于 2026-5-20 16:32
WX的ocr是那个大佬的?

是不是电脑版微信自带的?
4#
动物凶猛 发表于 2026-5-20 16:42
发票的规格型号那些应该都要用
5#
yingweifu 发表于 2026-5-20 16:42
WIN7系统,打开软件按照路径也填写了,回车以后软件就不见了。。。导出来的文件也不知道在哪里。。
6#
jun269 发表于 2026-5-20 16:44
现在发票不都是PDF或者OFD格式了吗?
7#
ilulyj 发表于 2026-5-20 17:02
好工具,谢谢分享
9#
dex5242 发表于 2026-5-20 18:42
jpg,直接识别pdf会不会更实用一些,实现批量识别
10#
shockwave123 发表于 2026-5-20 18:48
学习学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-21 02:18

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表