如何遍历含多商品发票的非结构化TXT并生成Pandas DataFrame
非结构化发票TXT文件的多商品数据提取问题
我有一个包含数百张发票及其对应商品的非结构化TXT文件,每张发票的商品数量为1到10个不等。该TXT文件格式大致如下:
-------REPORT-------- Invoice..: 2000 Product BarCode Price ASPIRIN 001001 5.00 Total: 5.00 Invoice..: 2001 Product BarCode Price LOSARTAN 005001 5.00 VITAMIN 002111 10.00 Total: 15.00
大多数发票仅含一个商品,针对这类情况,我使用以下代码可提取全部数据:
import re invoice = [] product = [] barcode = [] price = [] lines = [line.strip() for line in open('your_invoice_file.txt', 'r') if line.strip()] for idx, x in enumerate(lines): if 'Invoice..:' in x: invoice.append(re.search(r'(?<=Invoice..:).*', x).group(0).strip()) elif 'Product' in x: product.append(lines[idx+1]) barcode.append(lines[idx+2]) price.append(lines[idx+3])
但我无法解决发票含两个及以上商品时,正确提取商品名称、条形码和价格的问题。最终我希望生成如下结构的Pandas DataFrame:
| Invoice | Product | BarCode | Price |
|---|---|---|---|
| 2000 | Aspirin | 001001 | 5.00 |
| 2001 | Losartan | 005001 | 5.00 |
| 2001 | Vitamin | 002111 | 10.00 |
解决方案
核心思路是跟踪当前发票编号,在遇到Product表头后,循环提取后续的商品信息,直到碰到Total行或者下一张发票的开头。
以下是可处理多商品场景的代码:
import re import pandas as pd # 读取并清理文本行(去掉空行和首尾空格) with open('your_invoice_file.txt', 'r') as f: lines = [line.strip() for line in f if line.strip()] data = [] current_invoice = None i = 0 while i < len(lines): line = lines[i] # 匹配发票编号 if 'Invoice..:' in line: current_invoice = re.search(r'(?<=Invoice..:).*', line).group(0).strip() i += 1 # 碰到商品表头,开始提取商品 elif 'Product BarCode Price' in line: i += 1 # 跳过表头行 # 循环提取商品,直到遇到Total或下一张发票 while i < len(lines) and not lines[i].startswith('Total:') and not 'Invoice..:' in lines[i]: # 商品名称、条形码、价格是连续三行 product_name = lines[i].strip().title() barcode = lines[i+1].strip() price = lines[i+2].strip() # 添加到数据列表 data.append({ 'Invoice': current_invoice, 'Product': product_name, 'BarCode': barcode, 'Price': price }) i += 3 # 跳过当前商品的三行 else: i += 1 # 跳过其他行(比如Total行) # 转换为DataFrame df = pd.DataFrame(data) print(df)
代码说明:
- 清理文本行:先去掉空行和每行的首尾空格,避免干扰匹配
- 跟踪当前发票:每次遇到发票编号时,记录当前的发票号,后续商品都关联这个编号
- 循环提取商品:碰到商品表头后,连续读取三行作为一个商品的信息,直到碰到
Total或者下一张发票的开头,确保多商品能被全部提取 - 格式统一:用
title()把商品名称转为首字母大写的格式,和期望输出一致
运行后即可得到符合要求的DataFrame。
内容的提问来源于stack exchange,提问作者Leonardo Nascimento
相关产品推荐
相关产品推荐

