
本文介绍使用 python 正则表达式与键值映射字典,从格式不统一的纯文本文件中稳健提取关键业务字段(如客户号、发票号、订单日期等),支持多变关键词匹配与跨行内容捕获。
本文介绍使用 python 正则表达式与键值映射字典,从格式不统一的纯文本文件中稳健提取关键业务字段(如客户号、发票号、订单日期等),支持多变关键词匹配与跨行内容捕获。
在处理来自不同系统或人工录入的文本票据、发票或日志文件时,常见问题是:关键信息(如“Customer Nr.”、“Inv. Number:”、“Order date”)的表述形式多样、位置不固定、前后空格/标点不一致,甚至跨行出现。硬编码逐行解析极易失效。一个健壮的解决方案是构建语义映射字典 + 正则动态匹配的组合策略。
核心思路是:将业务语义(如 'Customer Number')作为统一键,其所有可能的原始文本变体(如 'customer number', 'cus. nr.', 'Customer Nr.')作为该键对应的正则候选模式;对每段文本,依次尝试各变体的模糊匹配,捕获其后紧跟的值内容。
以下是完整可运行的实现:
import re
# 定义语义键与其所有常见文本变体(支持大小写不敏感匹配)
values_dict = {
'Customer Number': ['Customer Nr.', 'customer number', 'cus. nr.', 'Customer Number', 'Kundennummer'],
'Order Number': ['Order number.', 'Order nr', 'order number', 'Order Number', 'Bestellnummer', 'Order #'],
'Invoice Number': ['Invoice Nr.', 'Inv. Number:', 'invoice number', 'Invoice Number', 'Rechnungsnummer', 'INV #'],
'Order Date': ['Order Date', 'Bestelldatum', 'Order date:', 'Datum'],
'Company Information': ['Company Name', 'Firmenname', 'Company:', 'Lieferadresse'],
'Invoice Company Information': ['Invoice Adress Company Name', 'Rechnungsadresse', 'Billing Address']
}
def extract_information(text: str, pattern_map: dict) -> dict:
"""
从输入文本中提取指定语义字段的值
支持冒号、空格分隔,自动去除首尾空白,并优先匹配首个有效变体
"""
results = {}
# 预编译正则以提升性能(尤其处理大量文件时)
for key, variations in pattern_map.items():
for variation in variations:
# 构建鲁棒模式:匹配关键词(可选后跟 : 或空格),后接非换行符内容(贪婪捕获)
pattern = rf"{re.escape(variation)}\s*[:\.]?\s*(.+?)(?=\n|$)"
match = re.search(pattern, text, re.IGNORECASE | re.DOTALL)
if match:
# 清理捕获值:去首尾空格,合并内部多余空白
value = re.sub(r'\s+', ' ', match.group(1).strip())
results[key] = value
break # 找到第一个匹配即停止,避免同义词重复覆盖
return results
# 示例文本(模拟真实多行混排的票据内容)
sample_text = """Company Name GmbH, Teststraße 24 , 01000 Sampleort
Customer Nr. 11111111
Invoice Nr. 22222
Invoice Adress Company Name 2 mbH, Test2straße 11, 01001 Sample2ort
Order number. 555555
Order Date 01.01.1999"""
# 执行提取
extracted = extract_information(sample_text, values_dict)
# 格式化输出(按需求顺序打印)
output_order = ['Company Information', 'Invoice Company Information',
'Customer Number', 'Order Number', 'Invoice Number', 'Order Date']
for field in output_order:
if field in extracted:
print(f"{field}: {extracted[field]}")
运行结果示例:
Company Information: Company Name GmbH, Teststraße 24 , 01000 Sampleort Invoice Company Information: Company Name 2 mbH, Test2straße 11, 01001 Sample2ort Customer Number: 11111111 Order Number: 555555 Invoice Number: 22222 Order Date: 01.01.1999
关键优化与注意事项:
- ✅ re.escape() 防止变体中的特殊字符(如 .、:)被误解析为正则元字符;
- ✅ re.IGNORECASE | re.DOTALL 确保大小写不敏感,且 . 可匹配换行符(应对跨行场景);
- ✅ 使用 (?=\n|$) 正向先行断言限制捕获范围,避免过度贪婪;
- ⚠️ 若值本身含换行(如地址跨多行),需改用更复杂的上下文匹配逻辑(例如基于段落分割预处理);
- ⚠️ 对高度非结构化文本,建议先做清洗(移除页眉页脚、标准化空格)再提取;
- ? 可扩展为批量处理:用 glob 读取 .txt 文件列表,循环调用 extract_information 并导出 CSV/JSON。
该方法平衡了灵活性与可维护性——新增字段只需扩展字典,无需重写逻辑,是文本数据清洗与信息抽取任务中的实用范式。










