Python requests发送post请求的编码问题

详细版本见个人博客:Python requests发送post请求的编码问题


在HTTP协议中,post提交的数据必须放在消息主体中,但是协议中并没有规定必须使用什么编码方式,从而导致了提交方式的不同。服务端根据请求头中的Content-Type字段来获知请求中的消息主体是用何种方式进行编码,再对消息主体进行解析。具体的编码方式包括如下:

  • application/x-www-form-urlencoded:以form表单形式提交数据,最常见也是大家最熟悉的
  • application/json:以json串提交数据。

下面使用requests来发送这两种编码的POST请求。

一、提交Form表单

requests提交Form表单,一般存在于网站的登录,用来提交用户名和密码。以http://httpbin.org/post为例,在requests中,以form表单形式发送post请求,只需要将请求的参数构造成一个字典,然后传给requests.post()的data参数即可。代码如下:

url = 'http://httpbin.org/post'
d = {'key1': 'value1', 'key2': 'value2'}
r = requests.post(url, data=d)
print(r.text)
{
  "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": "httpbin.org", 
    "User-Agent": "python-requests/2.20.0"
  }, 
  "json": null, 
  "origin": "121.249.15.110, 121.249.15.110", 
  "url": "https://httpbin.org/post"
}

这里返回的"Content-Type":"application/x-www-form-urlencoded",证明这是提交Form的方式。

二、提交json串

对于提交json串,主要是用于发送ajax请求中,动态加载数据。以NSFC网站为例,加载项目的方式为ajax,项目的内容在响应中。

下面是典型的错误用法:

url = "url"

headers = {'Content-Type': "application/json",
           'Host': "output.nsfc.gov.cn",
           'Origin': "http://output.nsfc.gov.cn",
           'Referer': "http://output.nsfc.gov.cn/fundingQuery",
           'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36",}

payload = {'adminID': "",
           'beginYear': "",
           ......}

response = requests.post(url = url,data = payload,headers = headers)
print(response.text)
'{\n\t"timestamp":1557026952651,\n\t"status":400,\n\t"error":"Bad Request",\n\t"exception":"org.springframework.http.converter.HttpMessageNotReadableException",\n\t"message":"JSON parse error: syntax error, expect {, actual error, pos 0, fastjson-version 1.2.38; nested exception is com.alibaba.fastjson.JSONException: syntax error, expect {, actual error, pos 0, fastjson-version 1.2.38",\n\t"path":"/baseQuery/data/supportQueryResultsData"\n}'

请求头已经跟抓包得到的保持一致了,加上了'Content-Type': "application/json"参数,但是无法正确得到响应。这是因为请求实体的格式错了,服务端无法解码。

正确方法1——把data进行json编码

正确的写法是把data进行json编码,再发送:

response = requests.post(url = url,data = json.dumps(payload),headers = headers)
'{\n\t"code":200,\n\t"data":{\n\t\t"iTotalRecords":76,\n\t\t"resultsData":[\n\t\t\t[\n\t\t\t\t"59607",\n\t\t\t\t"调节性树突状细胞负向调控烧伤所致过度炎症反应的信号转导机制研究",\n\t\t\t\t"81000847",\n\t\t\t\t"面上项目",\n\t\t\t\t"中国人民解放军总医院",\n\t\t\t\t"王强",\n\t\t\t\t"",\n\t\t\t\t"2010",\n\t\t\t\t"调节性树突状细胞;过度炎症反应;信号转导及转录活化因子-3;负向调控免疫;过继治疗",\n\t\t\t\t"true",\n\t\t\t\t"5;0;0;0;0",\n\t\t\t\t"100518",\n\t\t\t\t"",\n\t\t\t\t"218"\n\t\t\t]\n\t\t]\n\t},\n\t"message":"Success"\n}'

正确方法2——使用json参数发送

除了将data主动编码为json发送之外,requests还提供了一个json参数,自动使用json方式发送,而且在请求头中也不用显示声明’Content-Type’:’application/json’

url = "url"

headers = {'Host': "output.nsfc.gov.cn",
           'Origin': "http://output.nsfc.gov.cn",
           'Referer': "http://output.nsfc.gov.cn/fundingQuery",
           'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36",}

payload = {'adminID': "",
           'beginYear': "",
           ......}

response = requests.post(url = url,json = payload,headers = headers)
print(response.text)

同样可以正确得到响应:

'{\n\t"code":200,\n\t"data":{\n\t\t"iTotalRecords":76,\n\t\t"resultsData":[\n\t\t\t[\n\t\t\t\t"59607",\n\t\t\t\t"调节性树突状细胞负向调控烧伤所致过度炎症反应的信号转导机制研究",\n\t\t\t\t"81000847",\n\t\t\t\t"面上项目",\n\t\t\t\t"中国人民解放军总医院",\n\t\t\t\t"王强",\n\t\t\t\t"",\n\t\t\t\t"2010",\n\t\t\t\t"调节性树突状细胞;过度炎症反应;信号转导及转录活化因子-3;负向调控免疫;过继治疗",\n\t\t\t\t"true",\n\t\t\t\t"5;0;0;0;0",\n\t\t\t\t"100518",\n\t\t\t\t"",\n\t\t\t\t"218"\n\t\t\t]\n\t\t]\n\t},\n\t"message":"Success"\n}'

详细版本见个人博客:Python requests发送post请求的编码问题

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用 Requests 模块发送 POST 请求时,你需要在调用 `requests.post()` 函数时传入几个参数: 1. `url`: 这是你要发送 POST 请求的 URL。 2. `data`: 这是你要发送的数据。它可以是一个字典,列表,元组或字符串。如果你要发送表单数据,你应该使用字典并使用 `requests.post()` 函数的 `data` 参数传递它。 3. `json`: 这是你要发送的 JSON 数据。你可以使用这个参数来发送 JSON 格式的数据。 4. `headers`: 这是你要发送的 HTTP 头。你可以使用字典来指定 HTTP 头。 5. `cookies`: 这是你要发送的 cookie。你可以使用字典来指定 cookie。 6. `auth`: 这是你的身份验证信息。你可以使用元组来指定用户名和密码。 7. `timeout`: 这是等待服务器响应的最长时间(以秒为单位)。 例如,下面是使用 Requests 模块发送 POST 请求的示例代码: ``` import requests url = 'http://httpbin.org/post' data = {'key': 'value'} headers = {'Content-Type': 'application/json'} response = requests.post(url, data=data, headers=headers) print(response.text) ``` 这个示例代码向 `http://httpbin.org/post` 发送了一个 POST 请求,并使用 `data` 参数传递了一个字典作为表单数据,使用 `headers` 参数指定了 HTTP 头。 ### 回答2: Requests 模块发送 Post 请求的参数可以通过不同的方式传递。 第一种方式是通过 data 参数传递,可以将参数以字典形式传递给 data 参数,例如: ``` import requests data = {'key1': 'value1', 'key2': 'value2'} response = requests.post(url, data=data) ``` 第二种方式是通过 json 参数传递,可以将参数以字典形式传递给 json 参数,例如: ``` import requests data = {'key1': 'value1', 'key2': 'value2'} response = requests.post(url, json=data) ``` 第三种方式是通过 headers 参数传递,可以将参数以字典形式传递给 headers 参数,例如: ``` import requests headers = {'Content-Type': 'application/json'} response = requests.post(url, headers=headers) ``` 第四种方式是通过 cookies 参数传递,可以将参数以字典形式传递给 cookies 参数,例如: ``` import requests cookies = {'key1': 'value1', 'key2': 'value2'} response = requests.post(url, cookies=cookies) ``` 以上是 Requests 模块发送 Post 请求的一些常见参数传递方式,根据实际情况选择合适的方式进行参数传递。 ### 回答3: Requests 模块发送 post 请求时的参数可以通过 data 或者 json 参数来设置。 使用 data 参数时,可以传递一个字典类型的对象作为参数,其中包含了需要发送的数据。这个字典对象会被自动编码为表单形式的请求数据,然后发送给服务器。可以使用如下方式设置 data 参数: ```python import requests payload = {'key1': 'value1', 'key2': 'value2'} response = requests.post(url, data=payload) ``` 使用 json 参数时,可以传递一个字典类型的对象作为参数,其中包含了需要发送的数据。这个字典对象会被自动编码为 JSON 格式的请求数据,然后发送给服务器。可以使用如下方式设置 json 参数: ```python import requests payload = {'key1': 'value1', 'key2': 'value2'} response = requests.post(url, json=payload) ``` data 参数适用于普通的表单数据提交,而 json 参数适用于发送 JSON 数据的情况。根据实际需要选择合适的方式来设置参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值