银行交易PDF表格提取问题:Tabula与Camelot适配难题
解决银行交易PDF表格提取的列错位与拆分问题
针对你用Tabula和Camelot提取银行交易PDF表格时遇到的列错位、列拆分问题,直接给你可落地的解决方法:
一、修复列数据错位问题
1. 手动指定列边界坐标
自动列识别是错位的核心原因,直接用PDF阅读器(如Adobe Acrobat)测量每列的x轴起始/结束坐标,强制工具按指定边界分割:
# Tabula 示例 import tabula # 假设列边界x坐标为50,200,400,600,对应timestamp、narration、counterparty、amount列 df_list = tabula.read_pdf("bank_transactions.pdf", pages="all", columns=[50, 200, 400, 600], guess=False) # Camelot 示例 import camelot tables = camelot.read_pdf("bank_transactions.pdf", pages="all", columns=['50,200,400,600'], split_text=False)
2. 基于字段规则校验迁移数据
对关键列做格式校验,把错位的数据移回正确列:
import re import pandas as pd # 定义timestamp的格式正则(根据你的银行账单格式调整) timestamp_regex = r'\d{4}-\d{2}-\d{2}|\d{2}/\d{2}/\d{4}' def fix_misplaced_data(df): for idx, row in df.iterrows(): # 检查narration列是否存在timestamp格式内容,且原timestamp列为空 if pd.isna(row['timestamp']): match = re.search(timestamp_regex, str(row['narration'])) if match: df.at[idx, 'timestamp'] = match.group() df.at[idx, 'narration'] = str(row['narration']).replace(match.group(), '').strip() # 同理可处理counterparty列的错位情况 return df # 对提取后的DataFrame应用修复 fixed_df = fix_misplaced_data(df_list[0])
二、解决列拆分问题
1. 合并拆分的文本列
如果narration或counterparty被拆到相邻列,直接合并对应列后删除冗余列:
def merge_splitted_columns(df): # 假设拆分后的narration列名为narration、narration_1、narration_2 df['narration'] = df[['narration', 'narration_1', 'narration_2']].apply( lambda x: ' '.join([str(val).strip() for val in x if pd.notna(val)]), axis=1 ) # 合并counterparty拆分列 df['counterparty'] = df[['counterparty', 'counterparty_1']].apply( lambda x: ' '.join([str(val).strip() for val in x if pd.notna(val)]), axis=1 ) # 删除冗余拆分列 df = df.drop(['narration_1', 'narration_2', 'counterparty_1'], axis=1) return df merged_df = merge_splitted_columns(fixed_df)
2. 禁用工具的文本拆分功能
Camelot默认会拆分单元格内的换行文本,关闭该功能可以避免不必要的列拆分:
tables = camelot.read_pdf("bank_transactions.pdf", pages="all", columns=['50,200,400,600'], split_text=False) # 转换为DataFrame df = tables[0].df
额外优化建议
- 预处理PDF:用PyPDF2去除页面中的干扰元素(如页眉页脚),减少工具识别干扰:
from PyPDF2 import PdfReader, PdfWriter def remove_header_footer(input_path, output_path): reader = PdfReader(input_path) writer = PdfWriter() for page in reader.pages: # 设置裁剪框,保留中间表格区域(根据实际页面调整坐标) page.mediabox.lower_left = (0, 50) page.mediabox.upper_right = (600, 750) writer.add_page(page) with open(output_path, 'wb') as f: writer.write(f) # 预处理后再提取 remove_header_footer("original.pdf", "cleaned.pdf")
内容的提问来源于stack exchange,提问作者Gaurav Nambiar
相关产品推荐
相关产品推荐

