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

基于AWS Textract表单KV输出创建单行DataFrame并入库

问题描述

我用AWS Textract分析表单文档,得到了键值对结果。现在需要把这些键作为DataFrame的列标题,对应的值放到单行里,之后提取部分值插入数据库。我是编程新手,求指导。

原代码
import boto3
import sys
import re
import json
from collections import defaultdict


def get_kv_map(file_name):
    with open(file_name, 'rb') as file:
        img_test = file.read()
        bytes_test = bytearray(img_test)
        print('Image loaded', file_name)

    # process using image bytes
    client = boto3.client('textract')
    response = client.analyze_document(Document={'Bytes': bytes_test}, FeatureTypes=['FORMS'])

    # Get the text blocks
    blocks = response['Blocks']

    # get key and value maps
    key_map = {}
    value_map = {}
    block_map = {}
    for block in blocks:
        block_id = block['Id']
        block_map[block_id] = block
        if block['BlockType'] == "KEY_VALUE_SET":
            if 'KEY' in block['EntityTypes']:
                key_map[block_id] = block
            else:
                value_map[block_id] = block

    return key_map, value_map, block_map


def get_kv_relationship(key_map, value_map, block_map):
    kvs = defaultdict(list)
    for block_id, key_block in key_map.items():
        value_block = find_value_block(key_block, value_map)
        key = get_text(key_block, block_map)
        val = get_text(value_block, block_map)
        kvs[key].append(val)
    return kvs


def find_value_block(key_block, value_map):
    for relationship in key_block['Relationships']:
        if relationship['Type'] == 'VALUE':
            for value_id in relationship['Ids']:
                value_block = value_map[value_id]
    return value_block


def get_text(result, blocks_map):
    text = ''
    if 'Relationships' in result:
        for relationship in result['Relationships']:
            if relationship['Type'] == 'CHILD':
                for child_id in relationship['Ids']:
                    word = blocks_map[child_id]
                    if word['BlockType'] == 'WORD':
                        text += word['Text'] + ' '
                    if word['BlockType'] == 'SELECTION_ELEMENT':
                        if word['SelectionStatus'] == 'SELECTED':
                            text += 'X '

    return text


def print_kvs(kvs):
    for key, value in kvs.items():
        print(key, ":", value)


def search_value(kvs, search_key):
    for key, value in kvs.items():
        if re.search(search_key, key, re.IGNORECASE):
            return value


def main(file_name):
    key_map, value_map, block_map = get_kv_map(file_name)

    # Get Key Value relationship
    kvs = get_kv_relationship(key_map, value_map, block_map)
    print("\n\n== FOUND KEY : VALUE pairs ===\n")
    print_kvs(kvs)



if __name__ == "__main__":
    file_name = sys.argv[1]
    main(file_name)
原输出结果
== FOUND KEY : VALUE pairs ===

    Social#:  : ['XXXX ']
    Landlord Name:  : ['XXXX Trust ']
    Date:  : ['']
    Last Name:  : ['XXX ']
    Date of Birth:  : ['04/30/1959 ', '05/31/1955 ']
    State:  : ['CA ', 'CA ', 'CA ']
    Zip Code:  : ['92860 ', '92860 ', '92860 ']
    City:  : ['Norco ', 'Norco ', 'Norco ']
    Phone #:  : ['XXXX ', 'XXXX ', 'XXX ']
    Landlord Contact#:  : ['XXXX']
    Social Number/SIN#:  : ['XXXX ']
    Signature:  : ['']
    Primary Contact Number:  : ['XXXX ']
    Street Address:  : ['684 XXXX ']
    Physical Location Phone #:  : ['XXXXXXX ']
    Business Physical Street Address:  : ['684 XXXX ']
    Business Start Date of Current Ownership:  : ['05/01/2022 ']
    Amount Requested:  : ['550000.00 ']
    Home Address:  : ['1400 EXXXXX, 2201, Long Beach, CA 90802 ']
    Yes  : ['', 'X ', '', '']
    Industry Type: (Describe)  : ['manufacturing ']
    Business Legal Name:  : ['XXXXXX, LLC ']
    Business Trade Reference #3:  : ['XXXX ']
    Owner First Name  : ['Jim ']
    Billing Location Phone #:  : ['XXXX ']
    Est. Credit Score:  : ['700 ']
    LLC  : ['X ']
    Billing Street Address:  : ['684 XXXXX ']
    No  : ['', 'X ', 'X ', 'X ']
    Rented  : ['X ']
    Use of Proceeds:  : ['XXXXX ']
    Business Tax ID:  : ['XXXX ']
    Agent Name:  : ['']
    Date (M/D/YY)  : ['Sep 01 2022 ']
    Fax Number #:  : ['']
    Current Estimated MCA/ LINE OF CREDIT Balance  : ['350000.00 ']
    Credit Card Processing?  : ['X Yes No ']
    Business Trade Reference #1  : ['XXXXX']
    Business Website Address:  : ['']
    Mortgaged  : ['']
    Gross Annual Sales (from previous year's Tax return):  : ['2900000.00 ']
    Owner / Officer's Signature:  : ['']
    Business DBA Name:  : ['same ']
    Business Trade Reference #2:  : ['UPS ']
    State of Incorporation  : ['XXXX ']
    Ownership Percentage %  : ['37 ']
    Monthly Payment:  : ['7745.00 ']
    Name of Credit Card Processor  : ['XXXX']
    Owner / Officer's Name: (Print)  : ['XXXX ']
    LLP  : ['']
    Second Owner:  : ['XXXX ']
    Merchant Email Address  : ['XXXXX ']
    Fax:  : ['XXXXX ']
实现步骤

1. 清理并格式化KV数据

原输出的键存在多余空格、冒号,值多为列表类型(部分包含多个元素),先做清洗:

  • 去除键的首尾空格和末尾多余冒号
  • 将列表值合并为字符串(多值用逗号分隔)

在原代码基础上,修改main函数添加清洗逻辑:

import pandas as pd  # 新增导入pandas

def main(file_name):
    key_map, value_map, block_map = get_kv_map(file_name)

    # Get Key Value relationship
    kvs = get_kv_relationship(key_map, value_map, block_map)
    print("\n\n== FOUND KEY : VALUE pairs ===\n")
    print_kvs(kvs)
    
    # 清洗KV数据
    cleaned_kvs = {}
    for key, values in kvs.items():
        # 清理键格式
        cleaned_key = key.strip().rstrip(':')
        # 合并列表值为字符串,空值保留
        cleaned_value = ', '.join([v.strip() for v in values if v.strip()]) if any(v.strip() for v in values) else ''
        cleaned_kvs[cleaned_key] = cleaned_value
    
    print("\n\n== 清洗后的KEY : VALUE pairs ===\n")
    for key, value in cleaned_kvs.items():
        print(f"{key}: {value}")

2. 转换为Pandas DataFrame

将清洗后的字典转换为单行DataFrame,直接在main函数中添加:

# 转换为DataFrame
    df = pd.DataFrame([cleaned_kvs])
    print("\n\n== 生成的DataFrame ===")
    print(df)

3. 提取部分数据插入数据库

以SQLite为例,演示插入指定字段的逻辑,新增插入函数并调用:

import sqlite3  # 新增导入

def insert_to_db(df, db_name='form_data.db', table_name='form_records'):
    # 连接数据库(不存在则自动创建)
    conn = sqlite3.connect(db_name)
    # 选择需要插入的字段,可按需调整
    selected_cols = ['Business Legal Name', 'Amount Requested', 'Gross Annual Sales (from previous year\'s Tax return)', 'Owner First Name']
    df_selected = df[selected_cols]
    # 插入数据(表不存在则自动创建)
    df_selected.to_sql(table_name, conn, if_exists='append', index=False)
    # 关闭连接
    conn.close()
    print(f"\n数据已成功插入数据库 {db_name} 的 {table_name} 表")

# 在main函数末尾调用
insert_to_db(df)
完整修改后的代码
import boto3
import sys
import re
import json
from collections import defaultdict
import pandas as pd
import sqlite3


def get_kv_map(file_name):
    with open(file_name, 'rb') as file:
        img_test = file.read()
        bytes_test = bytearray(img_test)
        print('Image loaded', file_name)

    # process using image bytes
    client = boto3.client('textract')
    response = client.analyze_document(Document={'Bytes': bytes_test}, FeatureTypes=['FORMS'])

    # Get the text blocks
    blocks = response['Blocks']

    # get key and value maps
    key_map = {}
    value_map = {}
    block_map = {}
    for block in blocks:
        block_id = block['Id']
        block_map[block_id] = block
        if block['BlockType'] == "KEY_VALUE_SET":
            if 'KEY' in block['EntityTypes']:
                key_map[block_id] = block
            else:
                value_map[block_id] = block

    return key_map, value_map, block_map


def get_kv_relationship(key_map, value_map, block_map):
    kvs = defaultdict(list)
    for block_id, key_block in key_map.items():
        value_block = find_value_block(key_block, value_map)
        key = get_text(key_block, block_map)
        val = get_text(value_block, block_map)
        kvs[key].append(val)
    return kvs


def find_value_block(key_block, value_map):
    for relationship in key_block['Relationships']:
        if relationship['Type'] == 'VALUE':
            for value_id in relationship['Ids']:
                value_block = value_map[value_id]
    return value_block


def get_text(result, blocks_map):
    text = ''
    if 'Relationships' in result:
        for relationship in result['Relationships']:
            if relationship['Type'] == 'CHILD':
                for child_id in relationship['Ids']:
                    word = blocks_map[child_id]
                    if word['BlockType'] == 'WORD':
                        text += word['Text'] + ' '
                    if word['BlockType'] == 'SELECTION_ELEMENT':
                        if word['SelectionStatus'] == 'SELECTED':
                            text += 'X '

    return text


def print_kvs(kvs):
    for key, value in kvs.items():
        print(key, ":", value)


def search_value(kvs, search_key):
    for key, value in kvs.items():
        if re.search(search_key, key, re.IGNORECASE):
            return value

def insert_to_db(df, db_name='form_data.db', table_name='form_records'):
    # 连接数据库(不存在则自动创建)
    conn = sqlite3.connect(db_name)
    # 选择需要插入的字段,可按需调整
    selected_cols = ['Business Legal Name', 'Amount Requested', 'Gross Annual Sales (from previous year\'s Tax return)', 'Owner First Name']
    df_selected = df[selected_cols]
    # 插入数据(表不存在则自动创建)
    df_selected.to_sql(table_name, conn, if_exists='append', index=False)
    # 关闭连接
    conn.close()
    print(f"\n数据已成功插入数据库 {db_name} 的 {table_name} 表")


def main(file_name):
    key_map, value_map, block_map = get_kv_map(file_name)

    # Get Key Value relationship
    kvs = get_kv_relationship(key_map, value_map, block_map)
    print("\n\n== FOUND KEY : VALUE pairs ===\n")
    print_kvs(kvs)
    
    # 清洗KV数据
    cleaned_kvs = {}
    for key, values in kvs.items():
        # 清理键格式
        cleaned_key = key.strip().rstrip(':')
        # 合并列表值为字符串,空值保留
        cleaned_value = ', '.join([v.strip() for v in values if v.strip()]) if any(v.strip() for v in values) else ''
        cleaned_kvs[cleaned_key] = cleaned_value
    
    print("\n\n== 清洗后的KEY : VALUE pairs ===\n")
    for key, value in cleaned_kvs.items():
        print(f"{key}: {value}")
    
    # 转换为DataFrame
    df = pd.DataFrame([cleaned_kvs])
    print("\n\n== 生成的DataFrame ===")
    print(df)
    
    # 插入数据库
    insert_to_db(df)


if __name__ == "__main__":
    file_name = sys.argv[1]
    main(file_name)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:05:24