如何用Camelot PDF解析器处理含表格与非表格数据的PDF?
解决Camelot仅提取PDF表格、忽略非表格内容的问题
Camelot是专注于PDF表格提取的工具,本身不支持提取非表格文本。要同时获取PDF中的表格和非表格内容,需要搭配通用PDF文本提取库(比如pdfplumber),将两者的提取结果合并。
修改后的完整代码
from langchain.document_loaders.csv_loader import CSVLoader import camelot import uuid from camelot.core import TableList from collections import namedtuple import pdfplumber Document = namedtuple('Document', ['page_content', 'metadata']) def export_tables_as_csv(filepath): tables = camelot.read_pdf(filepath, backend="ghostscript") # 批量导出所有表格为CSV tables.export("tables.csv", f="csv", compress=True) def generate_random_filename(): return str(uuid.uuid4()) def get_non_table_text(page, table_bboxes): """从pdfplumber页面中剔除表格区域,提取非表格文本""" non_table_text = "" page_width = page.width page_height = page.height # 遍历页面字符,过滤表格区域内的内容 for char in page.chars: char_x = char['x0'] # 转换坐标:pdfplumber原点在左下角,Camelot在左上角 char_y = page_height - char['top'] in_table = False for bbox in table_bboxes: # bbox格式:(x1, y1, x2, y2),左上角为原点 if bbox[0] <= char_x <= bbox[2] and bbox[1] <= char_y <= bbox[3]: in_table = True break if not in_table: non_table_text += char['text'] return non_table_text.strip() def formChunksForTable(filepath=None, file_type=None, url=None): try: if not filepath: print("Error: Filepath is missing.") return [] all_docs = [] # 用Camelot提取所有页面的表格 tables = camelot.read_pdf(filepath, backend="ghostscript", flavor='stream', pages='all') # 用pdfplumber提取非表格文本 with pdfplumber.open(filepath) as pdf: for page_num, page in enumerate(pdf.pages, start=1): # 获取当前页的表格边界框 page_tables = [table for table in tables if table.page == page_num] table_bboxes = [table._bbox for table in page_tables] # 提取并添加非表格文本 non_table_content = get_non_table_text(page, table_bboxes) if non_table_content: metadata = {'source': f'non-table-page-{page_num}'} doc = Document(non_table_content, metadata) all_docs.append(doc) # 处理表格内容,转换为Document对象 if isinstance(tables, TableList): for table in tables: if table.df is not None and not table.df.empty: for row_idx, row in enumerate(table.df.values): page_content = ' '.join(str(cell) for cell in row) metadata = {'source': f'table-page-{table.page}-row-{row_idx+1}'} doc = Document(page_content, metadata) all_docs.append(doc) else: print(f"Warning: Table on page {table.page} is empty.") if not all_docs: print("No valid content (tables or non-table text) found in the PDF.") return all_docs except Exception as e: print(f"Error: {e}") return []
关键说明
- 坐标适配:pdfplumber与Camelot的坐标原点不同,通过转换字符y坐标,确保准确识别表格区域并过滤。
- 非文本过滤:遍历页面每个字符,仅保留表格区域外的内容,避免重复提取表格内的文本。
- 结果统一:将表格行和非表格文本都封装为
Document对象,保持输出格式一致,方便后续处理。
内容的提问来源于stack exchange,提问作者Pankaj Jaiswal
相关产品推荐
相关产品推荐

