requests发送post请求的三种⽅式
在http 协议中,post 提交的数据需放在消息主体的,但协议并没有规定必须使⽤什么编码⽅式,从⽽导致了提交⽅式的不同。服务端根据请求同⼀种的 Content-Type 字段来获
取请求中消息主体是⽤何种⽅式进⾏编码,再对消息主体进⾏解析。
具体的编码⽅式有: 
- application/x-www-form-urlencoded  # 以form表单形式提交数据,最常见也是⼤家最熟悉的
- application/json  # 以json串提交数据。
- multipart/form-data  # 上传⽂件
下⾯使⽤requests来发送上述三种编码的POST 请求
1、提交Form 表单    "Content-Type": "application/x-www-form-urlencoded"
requests提交Form表单,⼀般存在于⽹站的登录,⽤来提交⽤户名和密码。以 /post 为例,在requests中,以form表单形式发送post请求,只需要将请求的参数构造成⼀个字典,然后传给requests.p
ost()的data参数即可。
代码如下:
url = "/post"
d = {"key1":"value1","key2":"value2"}
r = requests.post(url, data=d) # requests.post() 中利⽤ data 属性
)
输出效果如下:
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "23",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "",
"User-Agent": "python-requests/2.22.0",
"X-Amzn-Trace-Id": "Root=1-60c06a74-78d1256647615a962d76bf9b"
},
"json": null,
"origin": "219.133.170.253",
"url": "/post"
}
< ⽹站可以显⽰你提交请求的内容,输出的”Content-Type”:”application/x-www-form-urlencoded”,证明这是提交Form的⽅式。
2、提交json串    "Content-Type": "application/json"
对于提交json串,主要是⽤于发送ajax请求中,动态加载数据。发送ajax请求的步骤
下⾯把请求头和请求实体列举⼀下:
错误写法:
import requests
url = "lazytools.feidee/v1/qrcode/log"
data = {
"category": 0,
"content": "。。。。。hahha'a",
"source": 1
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windo "Accept-Encoding": "gzip, deflate",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Connection": "keep-alive",
"Content-Type": "application/json",
"Host": "lazytools.feidee"
}
r = requests.post(url=url,data =data,headers=headers)
)
打印内容如下:
{"code":-1,"data":null,"message":"请求参数解析失败"}
即使写上了 'Content-Type':'application/json; charset=UTF-8' ,返回依然出错了,原因就在于你的请求实体的格式错了,服务端⽆法解码。
正确写法1:
正确代码是把data进⾏json编码,再发送。代码如下:
r = requests.post(url=url,data=json.dumps(data),headers=headers)# 利⽤ json 对字典序列化
这个时候再看⼀下打印内容,已经成功了
正确写法2:
处理将data主动编码为json发送之外,requests还提供了⼀个json参数,⾃动使⽤json⽅式发送,⽽且在请求头中也不⽤显⽰声明 'Content-Type':'application/json; charset=UTF-
8'。
完整代码如下
import requests
url = "lazytools.feidee/v1/qrcode/log"
data = {
"category": 0,
"content": "。。。。。hahha'a",
"source": 1
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windo "Accept-Encoding": "gzip, deflate",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Connection": "keep-alive",
"Host": "lazytools.feidee"
}
r = requests.post(url=url,json =data,headers=headers)  # 直接把字典传给 requests.post() 的 json 参数
)
3、上传⽂件      "Content-Type": "application/x-www-form-urlencoded"
上传⽂件在爬⾍中使⽤的很少,不过还是使⽤requests讲解⼀下使⽤⽅式。Content-Type类型为multipart/form-data,以multipart形式发送post请求,只需将⼀⽂件传给  requests.post() 的files参数即可。还是以  /post 为例,代码如下url = '/post'
files = {'file': open('', 'rb')}
r = requests.post(url, files=files)  # ⽂件传给 requests.post() 的 files 参数
)