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

AWS Lambda中Textract提取表单存为S3 CSV的代码问题排查

修复AWS Lambda中Textract表单提取并生成CSV到S3的问题

我帮你梳理下当前Lambda代码里的几个关键问题,以及修正后的完整实现方案:

原代码中的核心错误

  • S3上传逻辑错误:bucketName是字符串类型的桶名,不是boto3的Bucket对象,直接调用bucketName.upload_file()会抛出属性错误,因为字符串没有这个方法。
  • 文件未正确刷新/关闭:直接用open()创建文件对象却没使用上下文管理器(with语句),可能导致CSV内容还没完全写入磁盘就执行上传,生成空文件或不完整的文件。
  • TRP模块导入不完整:原代码里只导入了trp,但使用Document(response)需要明确导入Document类,否则会报错。
  • 资源初始化位置不合理:把boto3的s3、textract客户端初始化放在lambda_handler内部,每次函数执行都会重新初始化,影响性能(Lambda执行环境可以复用,放在外部能减少重复初始化的开销)。
  • 固定CSV文件名易冲突:直接用'textractData.csv'作为目标文件名,当多个文件上传时会互相覆盖,应该和原文件关联生成唯一文件名。

修正后的完整Lambda代码

import boto3
import urllib.parse
import os
import csv
from trp import Document  # 明确导入TRP的Document类

# 初始化boto3资源和客户端,放在函数外复用执行环境
s3 = boto3.resource('s3')
textract = boto3.client('textract')

def write_csv_to_s3(bucket_name, source_file_path, target_key):
    """将本地临时CSV文件上传到S3"""
    try:
        s3.meta.client.upload_file(source_file_path, bucket_name, target_key)
        print(f"成功上传CSV文件到S3: s3://{bucket_name}/{target_key}")
    except Exception as e:
        print(f"上传CSV到S3失败: {str(e)}")
        raise e

def lambda_handler(event, context):
    # 从S3事件中提取桶名和文件键
    bucket_name = event['Records'][0]['s3']['bucket']['name']
    document_key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    
    try:
        # 调用Textract分析表单(键值对)
        response = textract.analyze_document(
            Document={
                'S3Object': {
                    'Bucket': bucket_name,
                    'Name': document_key
                }
            },
            FeatureTypes=["FORMS"]
        )
        
        # 使用TRP解析Textract响应
        doc = Document(response)
        
        # 生成临时CSV文件路径
        temp_csv_path = "/tmp/form_extract.csv"
        
        # 使用上下文管理器确保文件正确写入和关闭
        with open(temp_csv_path, mode='w', newline='', encoding='utf-8') as csv_file:
            field_writer = csv.writer(csv_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
            # 写入表头
            field_writer.writerow(["Key", "Value"])
            
            # 遍历表单字段写入CSV
            for page in doc.pages:
                if page.form and page.form.fields:  # 先检查表单和字段是否存在,避免空引用错误
                    for field in page.form.fields:
                        # 处理可能的空键/值,避免写入报错
                        key_text = field.key.text if field.key else "无键"
                        value_text = field.value.text if field.value else "无值"
                        field_writer.writerow([key_text, value_text])
        
        # 生成目标S3键:替换原文件后缀为.csv,保留原路径
        target_csv_key = os.path.splitext(document_key)[0] + '.csv'
        
        # 上传临时CSV到S3
        write_csv_to_s3(bucket_name, temp_csv_path, target_csv_key)
        
        return {
            'statusCode': 200,
            'body': f"成功处理文件: {document_key},生成CSV: {target_csv_key}"
        }
    
    except Exception as e:
        print(f"处理文件失败: {str(e)}")
        return {
            'statusCode': 500,
            'body': f"处理错误: {str(e)}"
        }

关键修正点说明

  1. 资源初始化优化:把boto3的s3、textract客户端放在函数外部,Lambda执行环境复用的时候可以直接使用已初始化的客户端,提升执行效率。
  2. 正确的文件处理:用with open(...)上下文管理器,确保文件在写入完成后自动关闭并刷新缓冲区,避免内容丢失。
  3. S3上传修复:使用s3.meta.client.upload_file()方法,传入桶名、本地文件路径和目标S3键,这是正确的上传方式。
  4. 鲁棒性提升:增加了对page.form和field.key/value的空值检查,避免因为Textract返回的表单字段为空而触发报错。
  5. 唯一文件名:根据原文件的键生成对应的CSV文件名(替换后缀),避免多个文件上传时覆盖问题。
  6. 完整的错误处理:增加了try-except块捕获异常,并返回明确的状态码和错误信息,方便调试。

额外注意事项

  • 确保Lambda执行角色拥有AmazonTextractFullAccess和AmazonS3FullAccess(或更精细的权限,比如允许读取触发的S3桶、写入目标S3桶)。
  • 确认Lambda层中包含了trp模块(因为Lambda默认没有这个第三方模块,你需要把trp打包成层或者包含在部署包中)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:16:15