Python中如何使用Scrapy发送POST请求并传递JSON数据

需要带的数据为 data = {"a": [{"b": 'c'}]} 我用的这种写法一直不对, return scrapy.FormRequest( body=json.dumps(data), )


Python中如何使用Scrapy发送POST请求并传递JSON数据
13 回复

不需要 json.loads 直接传字典试试


在Scrapy里发POST请求带JSON数据,直接用scrapy.FormRequest不太对路,得用scrapy.Request,然后把method设成'POST'body里塞JSON字符串,再配好headers里的Content-Type

看个抓某API的完整例子:

import scrapy
import json

class MySpider(scrapy.Spider):
    name = 'json_post_spider'
    
    def start_requests(self):
        # 1. 准备JSON数据
        payload = {
            'page': 1,
            'limit': 20,
            'filter': {'category': 'books'}
        }
        
        # 2. 设置请求
        url = 'https://api.example.com/data'
        headers = {
            'Content-Type': 'application/json',
            'User-Agent': 'Mozilla/5.0'
        }
        
        # 3. 发送POST请求
        yield scrapy.Request(
            url=url,
            method='POST',
            headers=headers,
            body=json.dumps(payload),  # 关键:字典转JSON字符串
            callback=self.parse_response
        )
    
    def parse_response(self, response):
        # 4. 处理JSON响应
        try:
            data = json.loads(response.text)
            for item in data.get('results', []):
                yield {
                    'title': item.get('title'),
                    'price': item.get('price')
                }
        except json.JSONDecodeError:
            self.logger.error('Invalid JSON response')

几个关键点:

  1. body参数必须传字符串:用json.dumps()把字典转成JSON字符串,别直接传字典
  2. Content-Type必须设置headers里一定要有'Content-Type': 'application/json',不然服务器可能不认
  3. 处理响应:用json.loads()解析返回的JSON数据

如果参数是动态的,比如要翻页,可以这样:

def start_requests(self):
    for page in range(1, 6):
        payload = {'page': page, 'limit': 20}
        yield scrapy.Request(
            url='https://api.example.com/data',
            method='POST',
            headers={'Content-Type': 'application/json'},
            body=json.dumps(payload),
            meta={'page': page},  # 传递额外数据
            callback=self.parse_response
        )

scrapy.Request发JSON POST就这么简单,记得配好headers和body格式就行。

总结:用Request配JSON字符串和正确的Content-Type头。

试过, 不行, formdata 传字典, 或者 body 传 json 都是 状态码 408 的错误

可以试着传一下抓包 body 的截图,如果是"?1=2&3=4"这种的话需要可能需要换个思路

数据长这个样子, b 是一个编码, 是数字和英文的
data = {“lineItems”: [{“catalogNumber”: b}]}
用 requests 写没问题, 用了 scrapy 就是 408,

试一下,request = scrapy.Request( url, method=‘POST’,
body=json.dumps(my_data),)方式

body 里是 json 字符串,headers 中加 Content-Type: application/json

还是不行

408 Request Time-out

FormRequest 中 {‘ key’: ‘ value’, ‘ k’: ‘ v’}会被转化为’key=value&k=v’ 并且默认的 method 是 POST,你可以再看一下 body 的原始格式,看是这种 key-value 的形式还是 json 格式在作分析

这个提示并不是请求格式的问题吧,自己抓自己包看看

抓包,或者写一个测试用例接受请求过来的 body 和 head,比较有什么不同,实在不行用 request 替代好了。最新的 request-html 已经自带 html 解析,满足大部分爬虫场景。

formdata=data

回到顶部