如何从AWS Data Exchange批量下载订阅的合成数据集?
问题回顾
你订阅了AWS Data Exchange的免费合成数据集,手里有Revision ID、ARN、Dataset ID,数据集包含28个CSV文件,但没法直接打包下载,手动逐个下载太繁琐,又不想导出到Amazon S3。之前尝试用S3 CLI命令下载时报错,原因是错误地把Data Exchange的ARN当作S3桶名使用,不符合S3 CLI的参数格式要求。
可行的自动化下载方案
根据AWS官方文档,导出Data Exchange资产只有两种合法方式:导出到你有权限的S3存储桶,或者使用签名URL。既然你不想用S3存储桶,那EXPORT_ASSET_TO_SIGNED_URL就是最适合你的方案,具体思路如下:
1. 签名URL的核心逻辑
签名URL是AWS生成的临时可访问链接,有效期内可以直接通过HTTP请求下载对应资产,不需要经过中间S3存储桶。我们可以通过API或SDK批量生成所有资产的签名URL,再自动下载这些文件。
2. 用Boto3实现自动化批量下载
你提到找到的Python代码片段会创建临时S3桶,其实完全没必要——直接用Boto3调用Data Exchange的API生成签名URL,再批量下载即可,大致步骤和代码框架如下:
- 初始化Boto3的Data Exchange客户端
- 列出目标修订版本下的所有资产,拿到每个资产的ID
- 为每个资产创建
EXPORT_ASSET_TO_SIGNED_URL类型的作业 - 轮询作业状态,直到完成后获取签名URL
- 用HTTP请求库(比如
requests)下载每个URL对应的文件
示例代码框架:
import boto3 import requests import time # 初始化客户端(替换成你的区域) client = boto3.client('dataexchange', region_name='us-east-1') # 替换成你的数据集和修订版本ID DATASET_ID = 'b0b14e86c092855166507c15e045b844' REVISION_ID = '6011536d595840f7bd4412fca59e0f6b3' # 获取当前修订版本下的所有资产 assets = client.list_revision_assets( DataSetId=DATASET_ID, RevisionId=REVISION_ID )['Assets'] # 批量处理每个资产 for asset in assets: asset_id = asset['Id'] asset_name = asset['Name'] # 创建导出到签名URL的作业 job_response = client.create_job( Type='EXPORT_ASSET_TO_SIGNED_URL', Details={ 'ExportAssetToSignedUrl': { 'AssetId': asset_id, 'DataSetId': DATASET_ID, 'RevisionId': REVISION_ID } } ) job_id = job_response['Id'] # 等待作业完成(避免频繁轮询,加个短延迟) while True: job_status = client.get_job(JobId=job_id)['Status'] if job_status == 'COMPLETED': signed_url = client.get_job(JobId=job_id)['Details']['ExportAssetToSignedUrl']['SignedUrl'] break elif job_status == 'FAILED': print(f"下载资产 {asset_name} 失败,作业ID:{job_id}") break time.sleep(2) # 下载文件到本地 if signed_url: with open(asset_name, 'wb') as f: f.write(requests.get(signed_url).content) print(f"已成功下载:{asset_name}")
3. 解释你之前的S3 CLI报错原因
你之前执行的命令把Data Exchange的ARN直接当作S3桶名传给s3 cp,但S3 CLI的参数要求必须是合法的S3桶名或S3访问点ARN,Data Exchange的资产ARN完全不符合这个格式,所以才会抛出参数验证失败的错误。这种方式本身就不可行,因为Data Exchange的资产并不存储在你能直接访问的公开S3桶里。
总结
你没法直接把整个数据集打包下载,但可以通过签名URL+自动化脚本的方式批量下载所有28个CSV文件,完全不需要依赖中间S3存储桶。你创建的Gist如果是基于这个思路实现的,那就是正确的方向。
内容的提问来源于stack exchange,提问作者banderlog013

