Python正则提取字符串列表内容:交易数据解析异常求助
解决PDF提取交易数据的字段匹配问题
我看你用pytesseract从PDF里提取了交易记录,转成字典列表时遇到了字段匹配错误的问题——尤其是Item_Name、交易金额和余额经常串错,还有重复的错误条目。咱们来分析下原代码的问题,再给你一个更可靠的解决方案。
原代码的问题点
- 正则匹配不够精准:比如你的
item_and_name_pattern硬写了\d{2}-\d{2}-\d{4},但第四行的日期是08.10.2019(用点分隔),导致这个正则匹配不到,加上except pass直接跳过错误,就会复用之前循环里的变量值,出现重复的错误条目。 - 金额和余额的匹配逻辑混乱:原代码里先取total再用rstrip去掉,然后找amount,这种依赖字符串截断的方式很容易因为空格、格式差异出错。
- 异常处理太粗糙:
except: pass会掩盖错误,导致错误的变量值被带入下一次循环,生成错误的条目。
更可靠的解决方案
换个思路:每行的结构其实是「日期 + 交易描述 + 交易金额 + 余额」,咱们可以先精准提取日期,再把最后两个数值字段分离出来,剩下的就是交易描述。这样逻辑更清晰,容错性也更强。
修正后的代码
import re from collections import namedtuple # 你的原始交易数据 Statement= ['07-10-2019 UPI/927912685773/UPI/surya.balaji94@/Citibank 6,677.00 2,36,804.08', '07-10-2019 MOBILE BANKING DUT/CITIBANK 3,403.00 2,40,207.08', '07-10-2019 BIL/INFT/001818195728/82D3/ AJAY KUMAR JHA 6,080.00 2,46,287.08', '08.10.2019 MOBILE BANKING MMM TiMPS/928115182374/8161 Oct Mte/AMARJEET SIHDFC 4,411.00 250,698.08', '08-10-2019 BIL/INFT/001818636132/E3 BIk1 Pramod/ PRAMOD KUMAR P 6,599.00 2,57,297.08'] cols = ["Date", "Item_Name", "Transaction_Amount", "Balance"] Transaction = namedtuple("Transaction", cols) transactions = [] # 匹配日期:支持-或.分隔的DD-MM-YYYY格式,确保分隔符一致(比如08.10.2019不会误匹配成08-10.2019) date_pattern = re.compile(r"\d{2}([-.])\d{2}\1\d{4}") # 匹配所有带千分位逗号和两位小数的数值(覆盖交易金额和余额的格式) amount_pattern = re.compile(r"\d{1,3}(?:,\d{3})*\.\d{2}") for item in Statement: try: # 1. 提取日期 date_match = date_pattern.search(item) if not date_match: print(f"无法识别日期: {item}") continue date = date_match.group() # 2. 提取所有数值字段,最后两个分别是交易金额和余额 amounts = amount_pattern.findall(item) if len(amounts) < 2: print(f"数值字段不足: {item}") continue transaction_amount = amounts[-2] balance = amounts[-1] # 3. 提取交易名称:去掉日期、交易金额、余额后,清理多余空格 temp = item.replace(date, "").replace(transaction_amount, "").replace(balance, "").strip() # 把多个连续空格合并成一个,避免描述里有多余空格 item_name = re.sub(r"\s+", " ", temp) # 4. 生成交易对象并存入列表 t = Transaction(date, item_name, transaction_amount, balance) transactions.append(t) except Exception as e: print(f"处理条目失败: {item},错误信息: {str(e)}") continue # 转换为字典列表 out = [{k:v for k, v in f._asdict().items()} for f in transactions] # 打印测试结果 for entry in out: print(entry)
代码说明
- 日期匹配:用
\d{2}([-.])\d{2}\1\d{4}确保日期的分隔符一致(要么全是-,要么全是.),避免误匹配。 - 数值提取:用
amount_pattern提取所有符合格式的数值,直接取最后两个作为交易金额和余额,不管中间有多少空格或者格式变化。 - 交易描述清理:通过替换已知的日期、金额字段,再合并多余空格,得到干净的交易名称,避免了正则匹配的局限性。
- 异常处理:不再静默跳过错误,而是打印错误信息方便调试,避免错误变量复用。
正确输出结果
{'Date': '07-10-2019', 'Item_Name': 'UPI/927912685773/UPI/surya.balaji94@/Citibank', 'Transaction_Amount': '6,677.00', 'Balance': '2,36,804.08'} {'Date': '07-10-2019', 'Item_Name': 'MOBILE BANKING DUT/CITIBANK', 'Transaction_Amount': '3,403.00', 'Balance': '2,40,207.08'} {'Date': '07-10-2019', 'Item_Name': 'BIL/INFT/001818195728/82D3/ AJAY KUMAR JHA', 'Transaction_Amount': '6,080.00', 'Balance': '2,46,287.08'} {'Date': '08.10.2019', 'Item_Name': 'MOBILE BANKING MMM TiMPS/928115182374/8161 Oct Mte/AMARJEET SIHDFC', 'Transaction_Amount': '4,411.00', 'Balance': '250,698.08'} {'Date': '08-10-2019', 'Item_Name': 'BIL/INFT/001818636132/E3 BIk1 Pramod/ PRAMOD KUMAR P', 'Transaction_Amount': '6,599.00', 'Balance': '2,57,297.08'}
内容的提问来源于stack exchange,提问作者Subhojyoti Lahiri
相关产品推荐
相关产品推荐

