如何自动提取PDF财务文档两列表格中的关联数据?
问题描述
我正在开发一款读取财务文档并提取特定数据的代码。每个PDF文档结构不同,但目标数据始终在表格中,只是表格位置不固定。实际需求是:在两列的表格中,根据某一列的数据提取另一列的关联数据,例如表格数据为:
[A,Cash],[B,Card],[C,Swap],[D,Stock],[E,Derivative]
当输入C时,代码应返回Swap。请问如何实现全文档搜索并以字符串格式返回对应数据?
当前代码
import tkinter as tk from tkinter import filedialog import pdfplumber import re import datetime import dateparser # 选择PDF文件 def select_pdf_file(): root = tk.Tk() root.withdraw() # 隐藏主窗口 file_path = filedialog.askopenfilename(filetypes=[("PDF files", "*.pdf")]) return file_path def extract_and_merge_tables_with_dates(pdf_path): merged_data = [] date_regex = re.compile(r'(\d{1,2}\s+[a-zA-Z]+\s+\d{4}|\d{1,2}/\d{1,2}/\d{2,4}|\d{1,2}-[a-zA-Z].+-\d{2,4})|\d{1,2}-[a-zA-Z]+-\d{2,4}') with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: tables = page.extract_tables() for table in tables: has_dates = any(date_regex.match(str(cell)) for row in table for cell in row) if has_dates: for row in table[1:]: merged_data.append(row) # 使用dateparser将日期格式化为mm/dd/yyyy formatted_dates = [] for row in merged_data: formatted_row = [] for cell in row: if date_regex.match(str(cell)): parsed_date = dateparser.parse(str(cell)) if parsed_date: formatted_date = parsed_date.strftime("%-m/%d/%Y") formatted_row.append(formatted_date) else: formatted_row.append(cell) # 保留无法解析的单元格内容 formatted_dates.append(formatted_row) return formatted_dates def sort_dates(data): return sorted(data, key=lambda x: datetime.datetime.strptime(x[0], "%m/%d/%Y") if x else datetime.datetime.max) # 选择PDF文件 pdf_path = select_pdf_file() # 提取并合并包含日期的表格 formatted_data = extract_and_merge_tables_with_dates(pdf_path) # 按日期从旧到新排序数据 sorted_data = sort_dates(formatted_data) # 移除重复日期的行 unique_dates_set = set() unique_data = [] for row in sorted_data: date_string = row[0] if row else None if date_string not in unique_dates_set: unique_dates_set.add(date_string) unique_data.append(row) # 打印去重后的数据 for row in unique_data: print(row)
解决方案
要实现全文档搜索两列表格并根据输入值返回对应数据,可按以下思路修改代码:
- 筛选两列表格:遍历PDF所有页面的表格,只保留列数为2的表格,同时跳过空行或单元格不完整的行。
- 构建键值映射:将两列表格的第一列内容作为键,第二列内容作为值,存入字典实现快速查询(若存在重复键,后续行的内容会覆盖之前的)。
- 实现查询功能:接收用户输入的键,从字典中返回对应的值,未找到时返回提示信息。
修改后的完整代码如下:
import tkinter as tk from tkinter import filedialog import pdfplumber # 选择PDF文件 def select_pdf_file(): root = tk.Tk() root.withdraw() file_path = filedialog.askopenfilename(filetypes=[("PDF文件", "*.pdf")]) return file_path # 提取所有两列表格并构建键值映射字典 def build_key_value_map(pdf_path): key_value_map = {} with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: tables = page.extract_tables() for table in tables: # 只处理标准两列的表格 if len(table[0]) == 2: for row in table: # 跳过空行或单元格缺失的行 if len(row) >= 2 and row[0] is not None and row[1] is not None: # 清洗单元格内容,去除多余空格和换行 key = str(row[0]).strip().replace('\n', '') value = str(row[1]).strip().replace('\n', '') key_value_map[key] = value return key_value_map # 根据输入键查询对应值 def query_value(key_map, input_key): return key_map.get(input_key.strip(), "未找到对应数据") # 主执行流程 if __name__ == "__main__": pdf_path = select_pdf_file() if pdf_path: key_map = build_key_value_map(pdf_path) input_key = input("请输入要查询的键:") result = query_value(key_map, input_key) print(f"查询结果:{result}")
补充说明
- 若PDF表格存在合并单元格,
pdfplumber的extract_tables方法可能无法正确识别,需额外添加合并单元格的解析逻辑。 - 对于格式不规范的单元格内容(如包含换行、特殊符号),可在构建字典前进一步清洗字符串,提升查询准确性。
内容的提问来源于stack exchange,提问作者Hugo Actis
相关产品推荐
相关产品推荐

