Python爬虫遇到Request-Payload怎么办?

前言

最近想用 Python 自动地爬取某个站点里的图片,没想到其请求数据是以request payload格式传输给后端进行处理的。博主还是第一次遇到这种情况,写下这篇文章记录一下解决过程。

博主浏览器使用的是 Chrome,下文说的浏览器一律指的是 Chrome浏览器。

POST提交数据常见的几种Content-Type

在网络请求中常用的Content-Type有很多,但是在POST请求下我们常用的Content-Type大约有3种。

1.application/x-www-form-urlencoded

这应该是我们最常见到的POST数据提交方式,原生的表单默认提交方式就是这个,

我用站长工具模拟原生的POST请求,如图1-1:

Python爬虫遇到Request-Payload怎么办?_第1张图片

图1-1

第一个红框可以看到请求的Content-Type确实是application/x-www-form-urlencoded,第二个红框展示的是向后端请求的数据,它是经过浏览器解码然后展示给我们看的,实际上数据编码格式如图1-2:

图1-2

可以看到,我们请求的数据变成了键值对的形式,并且中间用&分隔,形如key1=val1&key2=val2

2.multipart/form-data

使用表单传数文件时,Content-Type必须是multipart/form-data,传输的文件会被分割成多个部分,每部分使用–boundary分割。

大体如图2-1:

图2-1

第二个红框数据也是经过浏览器解码的,原始数据如图2-2:

图2-2

3.application/json

一般情况下,我们遇到的POST请求数据编码格式都是application/x-www-form-urlencoded,但是这种格式有局限性,如果想向后端传输复杂的数据,如:

{
    "info": [
        {
            "name": "Kelvin",
            "age": 18
        }
    ]
}

这个时候,采用application/x-www-form-urlencoded对数据进行编码的话,就不是很方便。

对于像这种复杂的数据,一般都是以json格式直接传给后端进行解析。

博主在爬虫时遇到的就是Content-Type:application/json的情况,如图3-1:

图3-1

第二个红框也不像前两个一样是Form Data 而是变成了Request Payload,其中的数据也是经过浏览器解析的,原始数据如图3-2:

图3-2

图3-2

可以看出来,数据确实是以json格式进行传输的。

如果我们想模拟这种请求,如下代码是不行的:

import requests


headers = {
    'Content-Type': 'application/json',
    ......
}

data = {
    "n": "测试logo",

    "s": "TEST LOGO",

    "descr": "this is demo",
    "data": [],
    "p": 1,
    "dataPage": 0,
    "icon_lists": [],
    "icon_page": 1
}

url = 'https://www.logosc.cn/api/getAllInfo'
response = requests.post(url=url, data=data, headers=headers)

print(response.json())

根据请求的URL不同,报错信息也会一样,但无一例外的请求失败,如图3-3:

图3-3

遇到Request Payload的解决办法

碰到问题,我们首先求助的应该是官方文档,文档建议如下图4-1:

Python爬虫遇到Request-Payload怎么办?_第2张图片

图4-1

官方提供了两种方法让我们以 application/json 格式编码数据进行传输。

1.使用json.dumps()方法

json.dumps()方法将字典数据转化成json类型然后传给data参数,代码如下:

import requests
import json

 headers = {
 'Content-Type': 'application/json',
 ......
}
 data = {
 "n": "测试logo",
 "s": "TEST LOGO",
 "descr": "this is demo",
 "data": [],
 "p": 1,
 "dataPage": 0,
 "icon_lists": [],
 "icon_page": 1
 }
 url = 'https://www.logosc.cn/api/getAllInfo'
 response = requests.post(url=url, data=json.dumps(data), headers=headers)
 print(response.json())

2.将数据传给json参数

requests.post方法里有个json参数,当我们把数据传给json参数时,Content-Type会被自动的设置成application/json,代码如下:

import requests
 headers = {
 'Content-Type': 'application/json',
 ......
}
 data = {
 "n": "测试logo",
 "s": "TEST LOGO",
 "descr": "this is demo",
 "data": [],
 "p": 1,
 "dataPage": 0,
 "icon_lists": [],
 "icon_page": 1
 }
 url = 'https://www.logosc.cn/api/getAllInfo'
 response = requests.post(url=url, json=data, headers=headers)
 print(response.json())

结尾语

今天又爬出了一个小坑,很是开心,如果本文对你有所帮助,欢迎关注下方公众号「猿天罡」,不定期更新Python和算法相关的文章。see you!
Python爬虫遇到Request-Payload怎么办?_第3张图片

你可能感兴趣的:(Python)