You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python提取多表格PDF表格、指定键值对及优化输出格式咨询

现有代码的核心问题
  • 未做表格的独立结构化存储,所有表格拼接在同一个CSV文本中,既没有列数对齐处理,也没有空单元格补全逻辑,输出格式混杂。
  • Textract调用仅开启了TABLES特征,缺少FORMS特征支持,无法获取文档内键值对的文本关联关系,无法提取如「Example 1」「Example 2」这类指定键的对应取值。
  • 输出逻辑仅支持CSV格式写入,无多工作表写入能力,无法实现多表格拆分存储到Excel的需求。
分模块的改造实现方案

1. 调整Textract调用参数

开启表格+表单双特征提取能力,这是获取键值对关联关系的基础,将原代码中单行的特征参数修改为:

# 原代码为 FeatureTypes=['TABLES']
FeatureTypes=['TABLES', 'FORMS']

修改后,返回的文档blocks集合会同时包含表格结构、表单键值对的关联元数据,不需要自行通过位置猜测文本对应关系。

2. 重构表格结构化解析逻辑

替代原有的CSV字符串拼接逻辑,将每个识别到的表格转换为独立的二维矩阵结构,解决列错位、行顺序混乱的问题:

  • 遍历表格所有单元格时,按表格实际的最大列数补全空单元格,避免跨列场景下的列偏移。
  • 按行索引、列索引的数值排序,保证表格内容的顺序和PDF中的实际顺序一致。
    对应的替换函数示例:
def generate_table_matrix(table_result, blocks_map):
    rows_dict = get_rows_columns_map(table_result, blocks_map)
    # 计算当前表格的最大列数
    max_col = max([max(cols.keys()) for cols in rows_dict.values()])
    table_matrix = []
    # 按行号从小到大排序,保证行顺序正确
    for row_idx in sorted(rows_dict.keys()):
        row_data = []
        # 逐列补全空单元格
        for col_idx in range(1, max_col + 1):
            cell_text = rows_dict[row_idx].get(col_idx, "").strip()
            row_data.append(cell_text)
        table_matrix.append(row_data)
    return table_matrix

解析所有表格时,直接将每个表格的二维矩阵存入独立列表all_tables,不再做字符串拼接。

3. 指定键值对提取逻辑

基于开启FORMS特征后返回的键值对元数据,编写匹配逻辑提取目标内容:

  • 从blocks集合中筛选出类型为KEY_VALUE_SET、实体类型为KEY的块,作为所有候选键的来源。
  • 通过块自带的关联关系,找到每个键对应的VALUE块,提取完整文本作为对应取值。
  • 按照需求筛选目标键(如「Example 1」「Example 2」),生成目标键值对字典。
    对应的函数示例:
def extract_target_kv(blocks_map):
    kv_pairs = {}
    # 筛选所有KEY类型的块
    key_blocks = [
        block for block in blocks_map.values()
        if block['BlockType'] == 'KEY_VALUE_SET' and block['EntityTypes'][0] == 'KEY'
    ]
    for key_block in key_blocks:
        key_text = get_text(key_block, blocks_map).strip()
        # 查找键关联的VALUE块ID
        value_block_id = None
        for rel in key_block.get('Relationships', []):
            if rel['Type'] == 'VALUE':
                value_block_id = rel['Ids'][0]
                break
        if not value_block_id:
            continue
        # 提取值文本
        value_text = get_text(blocks_map[value_block_id], blocks_map).strip()
        kv_pairs[key_text] = value_text
    # 筛选需要的目标键
    target_key_list = ["Example 1", "Example 2"]
    return {k:v for k,v in kv_pairs.items() if k in target_key_list}

4. 规范Excel输出实现

通过openpyxl库实现多工作表写入,首先安装依赖:
pip install openpyxl
按照需求将数据分类写入不同工作表:

  • 每个提取到的表格单独占用一个工作表,命名为Table_1、Table_2,对应表格的实际顺序。
  • 单独新建一个KeyValues工作表,存放提取到的所有目标键值对,方便后续映射处理。
    对应的写入函数示例:
from openpyxl import Workbook

def write_structured_excel(all_tables, target_kv, output_path="structured_output.xlsx"):
    wb = Workbook()
    # 删除默认创建的空白工作表
    wb.remove(wb.active)
    # 逐表写入对应工作表
    for table_idx, table_data in enumerate(all_tables, start=1):
        ws = wb.create_sheet(title=f"Table_{table_idx}")
        for row in table_data:
            ws.append(row)
    # 写入键值对工作表
    ws_kv = wb.create_sheet(title="KeyValues")
    ws_kv.append(["键名", "对应取值"])
    for key, value in target_kv.items():
        ws_kv.append([key, value])
    wb.save(output_path)
落地注意事项
  • get_text函数提取的文本会因为逐单词拼接带前后空格,所有键名、单元格文本提取后要做strip()处理,避免因为多余空格导致的键名匹配失败。
  • 遇到跨页表格时,可以利用blocks自带的Page属性,将同一页面的表格归组,避免不同页的表格混排。
  • 写Excel时不要把所有表格堆在同一个工作表中,拆分工作表的结构完全匹配实际PDF中的表格边界,后续做数据映射时不需要再手动拆分内容。

内容的提问来源于stack exchange,提问作者Manz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.24 09:36:03