Scrapy爬虫S3上传异常及凭证配置疑问
解决Scrapy在EC2(带IAM角色)无法上传S3的问题
我之前也踩过类似的坑,本地依赖默认凭证链能正常上传,但EC2用IAM角色却不行,咱们一步步排查解决:
1. 先确认EC2的IAM角色配置没问题
这是最常见的根源,先把基础权限和关联逻辑搞对:
- 检查IAM角色的权限策略:确保角色有S3写入目标桶的权限,策略至少要包含
PutObject和ListBucket(Scrapy可能需要列出桶来验证路径),示例策略如下:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:PutObject", "s3:ListBucket"], "Resource": [ "arn:aws:s3:::foobar", "arn:aws:s3:::foobar/*" ] } ] }
- 确认角色已关联到EC2实例:在EC2控制台的实例详情里,检查「IAM角色」是否显示你配置的那个角色;也可以在EC2上执行
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/,如果能返回角色名称,说明关联成功。 - 测试基础S3访问:在EC2上安装AWS CLI(
sudo apt install awscli或pip install awscli),然后执行:
如果这步失败,说明是AWS IAM或网络的问题,先解决这个再看Scrapy的问题。echo "test content" > test.txt aws s3 cp test.txt s3://foobar/test_upload.txt
2. 检查Scrapy的配置细节
- FEED_URI格式验证:你当前的字符串拼接没问题,但可以换成更清晰的f-string避免语法错误:
注意S3路径里的特殊字符(比如冒号)是允许的,但要确保没有多余的空格或换行。FEED_URI = f's3://foobar/Year={today.year}/Month={today.month}/Day={today.day}/{today.strftime("%m-%d-%Y-%H:%M:%S")}.json' - 清理冲突配置:确保
custom_settings里没有任何注释外的AWS凭证配置(你已经注释了AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY,这步没问题),Scrapy会自动从环境变量或IAM角色获取凭证,手动配置会覆盖默认逻辑。 - 更新依赖版本:旧版本的
botocore(Scrapy S3 feed依赖的库)可能在处理IAM角色临时凭证时有bug,执行以下命令更新:pip install --upgrade scrapy botocore boto3
3. 查看Scrapy日志定位具体错误
运行爬虫时加上日志参数,能帮你快速定位问题:
scrapy crawl foobar --logfile scrapy_run.log --loglevel INFO
打开日志文件,搜索S3或error关键字:
- 如果看到
NoCredentialsError:说明EC2实例没获取到IAM角色的凭证,回到第一步检查角色关联和元数据服务访问(EC2元数据服务不能被安全组或防火墙拦截)。 - 如果看到
AccessDenied:说明IAM角色权限不够,检查策略里的资源是否包含目标桶的子路径(arn:aws:s3:::foobar/*)。 - 如果看到
EndpointConnectionError:说明网络不通,检查EC2的安全组是否允许出站到S3,或者是否需要配置VPC端点访问S3。
4. 网络与VPC配置检查
如果EC2在私有子网:
- 需要配置NAT网关让实例能访问公网S3,或者配置S3 VPC端点(推荐,更安全)。
- 若用VPC端点,要确保端点的策略允许你的IAM角色访问S3。
按上面的步骤排查,应该就能解决问题了,本质是确保EC2能通过IAM角色正常获取S3权限,同时Scrapy的配置没有干扰凭证的自动获取。
内容的提问来源于stack exchange,提问作者Zhongshuai
相关产品推荐
相关产品推荐

