如何使用pdfplumber处理含合并单元格的PDF表格?
处理PDF中带合并单元格的表格解析并转为JSON
原代码使用extract_tables的线条分割策略,无法识别合并单元格的跨度,导致提取后合并单元格对应位置出现空值,无法正确映射到JSON结构。以下是针对性解决方案:
核心思路
通过layout=True参数提取表格的单元格布局信息(包含坐标、行/列跨度),再根据这些信息填充合并单元格的内容,确保每行数据字段完整后,转换为JSON格式。
修改后的完整代码
def is_valid_table(table): min_rows, min_columns = 1, 2 return len(table) >= min_rows and len(table[0]) >= min_columns def extract_layout_tables(page): # 启用layout参数获取单元格布局信息 tables = page.extract_tables({ "vertical_strategy": "lines", "horizontal_strategy": "lines", "edge_min_length": 15, "min_words_vertical": 1, "layout": True # 关键参数:获取单元格的行/列跨度 }) return [table for table in tables if is_valid_table(table)] def merge_cells(table): processed_table = [] # 复制原始表格避免修改原数据 for row in table: processed_table.append([cell.copy() for cell in row]) # 处理跨行合并单元格 for row_idx in range(len(processed_table)): for col_idx in range(len(processed_table[row_idx])): cell = processed_table[row_idx][col_idx] if cell['rowspan'] > 1 and cell['text']: # 将内容填充到下方对应行 for offset in range(1, cell['rowspan']): if row_idx + offset < len(processed_table): processed_table[row_idx + offset][col_idx]['text'] = cell['text'] # 处理跨列合并单元格 for row_idx in range(len(processed_table)): col_idx = 0 while col_idx < len(processed_table[row_idx]): cell = processed_table[row_idx][col_idx] if cell['colspan'] > 1 and cell['text']: # 将内容填充到右侧对应列 for offset in range(1, cell['colspan']): if col_idx + offset < len(processed_table[row_idx]): processed_table[row_idx][col_idx + offset]['text'] = cell['text'] col_idx += 1 # 提取纯文本表格 text_table = [] for row in processed_table: text_row = [cell['text'] if cell['text'] else '' for cell in row] text_table.append(text_row) return text_table # 主处理流程 valid_tables = extract_layout_tables(page) page_text = page.extract_text() pdf_data["tables"] = [] for table in valid_tables: processed_text_table = merge_cells(table) # 匹配表格起始位置并获取标题(复用原有find_table_title函数) table_start_text = "\n".join(["".join(cell) for cell in processed_text_table]) table_start_index = page_text.find(table_start_text) table_title = find_table_title(page_text, table_start_index) # 转换为JSON结构 headers = processed_text_table[0] table_data = [dict(zip(headers, row)) for row in processed_text_table[1:]] pdf_data["tables"].append({ "title": table_title, "page_number": page.page_number, "data": table_data })
代码说明
extract_layout_tables函数:添加layout=True后,每个单元格变为包含text(内容)、rowspan(跨行数)、colspan(跨列数)的字典,为合并单元格处理提供依据。merge_cells函数:- 跨行合并:将合并单元格内容填充到下方所有属于该合并范围的单元格
- 跨列合并:将合并单元格内容填充到右侧所有属于该合并范围的单元格
- 最终输出纯文本的完整表格,确保每行每列都有对应内容
- JSON转换逻辑:基于处理后的完整纯文本表格,复用原有标题匹配和字典映射逻辑,保证输出JSON结构正确。
注意事项
- 若PDF表格线条不清晰,可将
vertical_strategy和horizontal_strategy改为text(基于文本位置分割),但lines策略对带明确边框的表格更准确。 - 若合并单元格跨度识别不准确,可微调
edge_min_length等参数,或添加额外逻辑验证单元格坐标范围。
内容的提问来源于stack exchange,提问作者Santhosh
相关产品推荐
相关产品推荐

