Scrapy发送POST请求返回400但requests库请求正常如何解决
Scrapy POST请求返回400问题解决方法
核心问题原因
- 你使用了
FormRequest提交JSON格式数据:FormRequest默认用于提交application/x-www-form-urlencoded格式的表单数据,会自动设置对应的请求头,就算你传入JSON序列化后的body,服务端收到请求后会按表单格式解析JSON串,自然解析失败返回400。 - 你提供的Scrapy代码存在缩进错误:
start_requests和parse方法没有缩进在Spider类内部,不会被Scrapy识别为爬虫的回调方法。
正确实现方式
方式1:使用Scrapy原生JsonRequest(推荐,Scrapy 2.2及以上版本支持)
用法和requests的post(json=xxx)完全一致,会自动设置Content-Type: application/json请求头,无需手动序列化JSON:
import scrapy from scrapy.http import JsonRequest class BiltorvetScraperSpider(scrapy.Spider): name = 'biltorvet' listings_url = "https://www.biltorvet.dk/Api/Search/Page" form_data = { "pageNumber": "1", "searchOrigin": "1", "searchValue": "22526899", "sort": "" } def start_requests(self): yield JsonRequest( url=self.listings_url, callback=self.parse, json=self.form_data ) def parse(self, response): print(response.json())
方式2:旧版本Scrapy手动指定请求头
如果你的Scrapy版本低于2.2,使用普通Request手动设置请求头即可:
import scrapy import json class BiltorvetScraperSpider(scrapy.Spider): name = 'biltorvet' listings_url = "https://www.biltorvet.dk/Api/Search/Page" form_data = { "pageNumber": "1", "searchOrigin": "1", "searchValue": "22526899", "sort": "" } def start_requests(self): yield scrapy.Request( url=self.listings_url, callback=self.parse, method="POST", body=json.dumps(self.form_data), headers={"Content-Type": "application/json"} ) def parse(self, response): print(response.json())
通用排查思路
如果修改后还是报错,可按以下步骤排查:
- 对比requests和Scrapy发出的请求头差异,把requests正常请求的头全部复制到Scrapy的请求头中,重点检查
User-Agent、Accept等头 - 使用scrapy shell调试请求,打印
request.headers和request.body确认和requests的请求内容一致 - 检查请求参数的类型是否匹配,比如部分接口要求
pageNumber为数字类型而非字符串
内容的提问来源于stack exchange,提问作者Ubaid
相关产品推荐
相关产品推荐

