批量汇总XML格式的发票信息

场景

将批量的XML发票信息提取汇总到EXCEL中

解析XML发票

python 复制代码
import xml.etree.ElementTree as ET

tree = ET.parse("./【365约车特选-39.54元-1个行程】高德打车电子发票.xml")
root = tree.getroot()

for child in root:
    print("一级分支",child.tag, child.attrib)
    for subchild in child:
        print("--二级分支",subchild.tag, subchild.attrib,subchild.text)
        for subsubchild in subchild:
            print("----三级分支", subsubchild.tag,subsubchild.attrib,subsubchild.text)
复制代码
一级分支 Header {}
--二级分支 EIid {} 26327000001329568432
--二级分支 EInvoiceTag {} SWEI3200
--二级分支 Version {} 0.32
--二级分支 InherentLabel {} None
----三级分支 InIssuType {} None
----三级分支 EInvoiceType {} None
----三级分支 GeneralOrSpecialVAT {} None
----三级分支 TaxpayerType {} None
--二级分支 UndefinedLabel {} None
----三级分支 Label {} None
----三级分支 Label {} None
----三级分支 Label {} None
一级分支 EInvoiceData {}
--二级分支 SellerInformation {} None
----三级分支 SellerIdNum {} 91320981MAEBB5QA34
----三级分支 SellerName {} 昆明盛智易联科技有限公司东台分公司
----三级分支 SellerAddr {} 东台沿海经济区科创大厦415
----三级分支 SellerTelNum {} 18108755741
----三级分支 SellerBankName {} 中信银行北京北辰支行
----三级分支 SellerBankAccNum {} 8110701013603001914
--二级分支 BuyerInformation {} None
----三级分支 BuyerIdNum {} 91xxxxxxxxxxxxxxxx3
----三级分支 BuyerName {} xxxxxx有限责任公司
----三级分支 BuyerAddr {} None
----三级分支 BuyerTelNum {} None
----三级分支 BuyerBankName {} None
----三级分支 BuyerBankAccNum {} None
--二级分支 BasicInformation {} None
----三级分支 TotalAmWithoutTax {} 38.39
----三级分支 TotalTaxAm {} 1.15
----三级分支 TotalTax-includedAmountInChinese {} 叁拾玖元伍角肆分
----三级分支 TotalTax-includedAmount {} 39.54
----三级分支 RequestTime {} 2026-07-18 23:45:14
----三级分支 Drawer {} 杨艳彩
--二级分支 IssuItemInformation {} None
----三级分支 ItemName {} *交通运输服务*客运服务费
----三级分支 MeaUnits {} None
----三级分支 Quantity {} 1
----三级分支 UnPrice {} 39.35
----三级分支 Amount {} 39.35
----三级分支 TaxRate {} 0.030000
----三级分支 ComTaxAm {} 1.18
----三级分支 TotaltaxIncludedAmount {} 40.53
----三级分支 TaxClassificationCode {} 3010101020203000000
--二级分支 IssuItemInformation {} None
----三级分支 ItemName {} *交通运输服务*客运服务费
----三级分支 Amount {} -0.96
----三级分支 TaxRate {} 0.030000
----三级分支 ComTaxAm {} -0.03
----三级分支 TotaltaxIncludedAmount {} -0.99
----三级分支 TaxClassificationCode {} 3010101020203000000
--二级分支 SpecificInformation {} None
--二级分支 AdditionalInformation {} None
----三级分支 Remark {} None
一级分支 TaxSupervisionInfo {}
--二级分支 InvoiceNumber {} 26327000001329568432
--二级分支 IssueTime {} 2026-07-18
--二级分支 TaxBureauCode {} 13200000000
--二级分支 TaxBureauName {} 国家税务总局江苏省税务局
一级分支 ptbh {}

寻找标签数据

root.findall()

仅查找标记为当前元素直接子级的元素

python 复制代码
root.findall(".//ItemName")
复制代码
[<Element 'ItemName' at 0x10c60aac0>, <Element 'ItemName' at 0x10c60aa20>]
python 复制代码
root.findall(".//ItemName")[0].text
复制代码
'*交通运输服务*客运服务费'
python 复制代码
root.findall(".//ItemName")[1].text
复制代码
'*交通运输服务*客运服务费'
python 复制代码
root.findall(".//IssuItemInformation/ItemName")[0].text
复制代码
'*交通运输服务*客运服务费'

root.find()

找到 第一 带有特定标签的子项

python 复制代码
root.find(".//TotalTax-includedAmount").text
复制代码
'39.54'

完整脚本代码

python 复制代码
import xml.etree.ElementTree as ET
from openpyxl import Workbook
from tqdm import tqdm      # 进度条工具
import os
from datetime import datetime
wb = Workbook()
ws = wb.active

now = datetime.now()
now = now.strftime("%Y-%m-%d %H-%M-%S")

print("当前日期和时间:", now)

# 获取当前工作目录的完整路径
current_directory_path = os.getcwd()
# 获取当前工作目录的名称
current_directory_name = os.path.basename(current_directory_path)

print("当前工作目录的完整路径:", current_directory_path)
print("当前工作目录的名称:", current_directory_name)


filenames = os.listdir('.')
path_files = []
for filename in filenames:
    filename = filename.split('.')
    if filename[-1] == 'xml':
        filename = str.join('.',filename)
        path_file = "./" + filename
        path_files.append(path_file)

print(f"文件夹下总共{len(path_files)} 个XML发票文件")


china_name = ["文件名","文件类型","发票号码","开票时间","税务局代码","税务局名称","票据编号","购买方名称","购买方税号","销售方名称","销售方税号","销售方电话","销售方开户银行","销售方开会银行账号","项目名称","规格型号","单位","数量","单价","金额","税率/征收率","税额","价税合计(小写)","价税合计(大写)"]

for i in range(len(china_name)):
    ws.cell(row=1,column=i+1).value = china_name[i]




def parse_xml_invoice(xml_path):
    tree = ET.parse(xml_path)
    root = tree.getroot()
    # 提取关键字段
    try:
        InvoiceNumber = root.find(".//InvoiceNumber").text
    except Exception as e:
        InvoiceNumber = "未提取成功"
        print(f"文件{xml_path}遇到 InvoiceNumber 参数报错{e}")
        
    try:
        IssueTime = root.find(".//IssueTime").text
    except Exception as e:
        IssueTime = "未提取成功"
        print(f"文件{xml_path}遇到 IssueTime 参数报错{e}")
        
    try:
        TaxBureauCode = root.find(".//TaxBureauCode").text
    except Exception as e:
        TaxBureauCode = "未提取成功"
        print(f"文件{xml_path}遇到 TaxBureauCode 参数报错{e}")
        
    try:
        TaxBureauName = root.find(".//TaxBureauName").text
    except Exception as e:
        TaxBureauName = "未提取成功"
        print(f"文件{xml_path}遇到 TaxBureauName 参数报错{e}")
        
    try: 
        ptbh = root.find(".//ptbh").text
    except Exception as e:
        ptbh = "未提取成功"
        print(f"文件{xml_path}遇到 ptbh 参数报错{e}")
        
    
    try:
        BuyerName = root.find(".//BuyerName").text
    except Exception as e:
        BuyerName = "未提取成功"
        print(f"文件{xml_path}遇到 BuyerName 参数报错{e}")
        
    try:
        BuyerIdNum = root.find(".//BuyerIdNum").text
    except Exception as e:
        BuyerIdNum = "未提取成功"
        print(f"文件{xml_path}遇到 BuyerIdNum 参数报错{e}")
        
    try:
        SellerName = root.find(".//SellerName").text
    except Exception as e:
        SellerName = "未提取成功"
        print(f"文件{xml_path}遇到 SellerName 参数报错{e}")
        
    try:
        SellerIdNum = root.find(".//SellerIdNum").text
    except Exception as e:
        SellerIdNum = "未提取成功"
        print(f"文件{xml_path}遇到 SellerIdNum 参数报错{e}")
        
    try:
        SellerTelNum = root.find(".//SellerTelNum").text
    except Exception as e:
        SellerTelNum = "未提取成功"
        print(f"文件{xml_path}遇到 SellerTelNum 参数报错{e}")
        
    try:
        SellerBankName = root.find(".//SellerBankName").text
    except Exception as e:
        SellerBankName = "未提取成功"
        print(f"文件{xml_path}遇到 SellerBankName 参数报错{e}")
        
    try:
        SellerBankAccNum = root.find(".//SellerBankAccNum").text
    except Exception as e:
        SellerBankAccNum = "未提取成功"
        print(f"文件{xml_path}遇到 SellerBankAccNum 参数报错{e}")

    ## 判断项目名目有几行
    try:
        IssuItemInformation_list = root.findall(".//IssuItemInformation")
        if len(IssuItemInformation_list) >= 2:
            ItemName = "多个项目目录,未提取"
            SpecMod = "多个项目目录,未提取"
            MeaUnits = "多个项目目录,未提取"
            Quantity = "多个项目目录,未提取"
            UnPrice = "多个项目目录,未提取"
            Amount = "多个项目目录,未提取"
            TaxRate = "多个项目目录,未提取"
            ComTaxAm = "多个项目目录,未提取"
        else:
            try:
                ItemName = root.find(".//ItemName").text
            except Exception as e:
                ItemName = "未提取成功"
                print(f"文件{xml_path}遇到 ItemName 参数报错{e}")
                
            try:
                SpecMod = root.find(".//SpecMod").text
            except Exception as e:
                SpecMod = "未提取成功"
                print(f"文件{xml_path}遇到 SpecMod 参数报错{e}")
                
            try:
                MeaUnits = root.find(".//MeaUnits").text
            except Exception as e:
                MeaUnits = "未提取成功"
                print(f"文件{xml_path}遇到 MeaUnits 参数报错{e}")
                
            try:
                Quantity = root.find(".//Quantity").text
            except Exception as e:
                Quantity = "未提取成功"
                print(f"文件{xml_path}遇到 Quantity 参数报错{e}")
                
            try:
                UnPrice = root.find(".//UnPrice").text
            except Exception as e:
                UnPrice = "未提取成功"
                print(f"文件{xml_path}遇到 UnPrice 参数报错{e}")
                
            try:
                Amount = root.find(".//Amount").text
            except Exception as e:
                Amount = "未提取成功"
                print(f"文件{xml_path}遇到 Amount 参数报错{e}")
                
            try:
                TaxRate = root.find(".//TaxRate").text
            except Exception as e:
                TaxRate = "未提取成功"
                print(f"文件{xml_path}遇到 TaxRate 参数报错{e}")
                
            try:
                ComTaxAm = root.find(".//ComTaxAm").text
            except Exception as e:
                ComTaxAm = "未提取成功"
                print(f"文件{xml_path}遇到 ComTaxAm 参数报错{e}")
    except Exception as e:
        print(f"文件{xml_path}遇到 IssuItemInformation 分支 参数报错{e}")
    
    try:
        TotalTax_includedAmount = root.find(".//TotalTax-includedAmount").text
    except Exception as e:
        TotalTax_includedAmount = "未提取成功"
        print(f"文件{xml_path}遇到 TotalTax_includedAmount 参数报错{e}")

    try:
        TotalTax_includedAmountInChinese = root.find(".//TotalTax-includedAmountInChinese").text
    except Exception as e:
        TotalTax_includedAmountInChinese = "未提取成功"
        print(f"文件{xml_path}遇到 TotalTax_includedAmountInChinese 参数报错{e}")

    context = {}
    context = {
        "文件名":xml_path,
        "文件类型":"XML",
        "发票号码":InvoiceNumber,
        "开票时间":IssueTime,
        "税务局代码":TaxBureauCode,
        "税务局名称":TaxBureauName,
        "票据编号":ptbh,
        "购买方名称":BuyerName,
        "购买方税号":BuyerIdNum,
        "销售方名称":SellerName,
        "销售方税号":SellerIdNum,
        "销售方电话":SellerTelNum,
        "销售方开户银行":SellerBankName,
        "销售方开会银行账号":SellerBankAccNum,
        "项目名称":ItemName,
        "规格型号":SpecMod,
        "单位":MeaUnits,
        "数量":Quantity,
        "单价":UnPrice,
        "金额":Amount,
        "税率/征收率":TaxRate,
        "税额":ComTaxAm,
        "价税合计(小写)":TotalTax_includedAmount,
        "价税合计(大写)":TotalTax_includedAmountInChinese
    }
    
    return context


i=2
for path_file in path_files:
    
    xml_path = path_file

    contexts = parse_xml_invoice(xml_path)
    ws.cell(row=i,column=1).value = contexts["文件名"]
    ws.cell(row=i,column=2).value = contexts["文件类型"]
    ws.cell(row=i,column=3).value = contexts["发票号码"]
    ws.cell(row=i,column=4).value = contexts["开票时间"]
    ws.cell(row=i,column=5).value = contexts["税务局代码"]
    ws.cell(row=i,column=6).value = contexts["税务局名称"]
    ws.cell(row=i,column=7).value = contexts["票据编号"]
    ws.cell(row=i,column=8).value = contexts["购买方名称"]
    ws.cell(row=i,column=9).value = contexts["购买方税号"]

    ws.cell(row=i,column=10).value = contexts["销售方名称"]
    ws.cell(row=i,column=11).value = contexts["销售方税号"]
    ws.cell(row=i,column=12).value = contexts["销售方电话"]
    ws.cell(row=i,column=13).value = contexts["销售方开户银行"]
    ws.cell(row=i,column=14).value = contexts["销售方开会银行账号"]
    ws.cell(row=i,column=15).value = contexts["项目名称"]
    ws.cell(row=i,column=16).value = contexts["规格型号"]
    ws.cell(row=i,column=17).value = contexts["单位"]
    ws.cell(row=i,column=18).value = contexts["数量"]
    ws.cell(row=i,column=19).value = contexts["单价"]
    ws.cell(row=i,column=20).value = contexts["金额"]
    ws.cell(row=i,column=21).value = contexts["税率/征收率"]
    ws.cell(row=i,column=22).value = contexts["税额"]
    ws.cell(row=i,column=23).value = contexts["价税合计(小写)"]
    ws.cell(row=i,column=24).value = contexts["价税合计(大写)"]
    i = i+1
        
wb.save(f'./{current_directory_name}_发票汇总_{str(now)}.xlsx')
print("Finish")
相关推荐
90后的晨仔18 小时前
Python 开发完全指南:从入门到工程化落地
python
胡耀超19 小时前
从一次批量爬取到生产同步:问题变了,建设边界也要跟着变
爬虫·python·系统架构·数据治理·数据同步·接口设计·爬虫工程
旅僧19 小时前
王树森老师强化学习--同声传译版3
python·深度学习
梦想不只是梦与想19 小时前
python中精度处理:decimal
python·float·精度丢失·decimal·浮点运算
大模型码小白19 小时前
向量化引擎与 AI 排障:当 SIMD 遇到异常检测,存储诊断的范式转移
java·大数据·数据库·人工智能·python
雪的季节19 小时前
【无标题】
linux·服务器·python
sa1002720 小时前
搭建京东评论监控系统,自动捕捉新增评价,快速挖掘用户真实痛点
python
weixin_4617694020 小时前
anaconda安装pytorch安装python
人工智能·pytorch·python
梅雅达编程笔记21 小时前
编程启蒙|Scratch 转 Python 系列第10天:问答闯关游戏实战(AI题库管理+随机出题实战)
人工智能·python·游戏·青少年编程