最近想用 Python 自动地爬取某个站点里的图片,没想到其请求数据是以request payload
格式传输给后端进行处理的。博主还是第一次遇到这种情况,写下这篇文章记录一下解决过程。
博主浏览器使用的是 Chrome,下文说的浏览器一律指的是 Chrome浏览器。
在网络请求中常用的Content-Type有很多,但是在POST请求下我们常用的Content-Type大约有3种。
这应该是我们最常见到的POST数据提交方式,原生的表单默认提交方式就是这个,
我用站长工具模拟原生的POST请求,如图1-1:
图1-1第一个红框可以看到请求的Content-Type
确实是application/x-www-form-urlencoded
,第二个红框展示的是向后端请求的数据,它是经过浏览器解码然后展示给我们看的,实际上数据编码格式如图1-2:
可以看到,我们请求的数据变成了键值对的形式,并且中间用&
分隔,形如key1=val1&key2=val2
。
使用表单传数文件时,Content-Type必须是multipart/form-data
,传输的文件会被分割成多个部分,每部分使用–boundary分割。
大体如图2-1:
图2-1第二个红框数据也是经过浏览器解码的,原始数据如图2-2:
图2-2一般情况下,我们遇到的POST请求数据编码格式都是application/x-www-form-urlencoded
,但是这种格式有局限性,如果想向后端传输复杂的数据,如:
{
"info": [
{
"name": "Kelvin",
"age": 18
}
]
}
这个时候,采用application/x-www-form-urlencoded
对数据进行编码的话,就不是很方便。
对于像这种复杂的数据,一般都是以json格式直接传给后端进行解析。
博主在爬虫时遇到的就是Content-Type:application/json
的情况,如图3-1:
第二个红框也不像前两个一样是Form Data
而是变成了Request Payload
,其中的数据也是经过浏览器解析的,原始数据如图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碰到问题,我们首先求助的应该是官方文档,文档建议如下图4-1:
图4-1官方提供了两种方法让我们以 application/json
格式编码数据进行传输。
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())
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!