如何使用Scrapy向API提交multipart/form-data类型POST请求?
搞定Scrapy提交multipart/form-data返回400的问题
嘿,我看你用requests能成功提交,但Scrapy就返回400,核心问题其实出在请求头的设置遗漏上,咱们一步步来解决:
先看你Scrapy代码的问题所在
你在requests代码里特意设置了Content-Type为MultipartEncoder的content_type(这个值包含了关键的boundary信息,API靠它解析multipart格式),但在Scrapy代码里只加了Content-Length,完全没加这个Content-Type头!这肯定会让API看不懂你的请求格式,直接返回400。
另外,Scrapy会自动计算并添加Content-Length,手动设置反而可能因为编码细节出现长度不匹配,建议直接删掉手动设置的Content-Length。
修正你的现有代码
把Scrapy代码改成这样,就能和requests一样成功了:
from requests_toolbelt.multipart.encoder import MultipartEncoder # 替换成你的实际表单数据 data = { 'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20', 'grant_type': 'password' } encoder = MultipartEncoder( data, boundary='-----------------------------265001916915724') headers = {} # 重点:必须添加这个包含boundary的Content-Type headers['Content-Type'] = encoder.content_type yield scrapy.Request( url=urls, method='POST', headers=headers, body=encoder.to_string(), callback=self.your_callback # 记得换成你自己的回调函数 )
更省心的Scrapy原生写法
其实Scrapy本身就支持生成multipart/form-data请求,不用依赖requests_toolbelt,代码更简洁:
# 普通表单字段 formdata = { 'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20', 'grant_type': 'password' } # 只要传个空的files参数,Scrapy就会自动用multipart/form-data编码请求 yield scrapy.FormRequest( url=urls, formdata=formdata, files={}, callback=self.your_callback )
这个写法不需要手动处理encoder和boundary,Scrapy会帮你搞定一切,适合没有文件上传的场景。
总结下为啥requests能成
因为requests里你完整传递了API需要的Content-Type头,而Scrapy代码里漏掉了这个关键信息,导致API无法解析你的请求格式。补上之后就能正常工作啦!
内容的提问来源于stack exchange,提问作者mtianyan
相关产品推荐
相关产品推荐

