POST請求用於向伺服器提交資料,比如提交一個表單新建一個使用者、或修改一個使用者資訊等操作。
對於POST請求,我們可以通過瀏覽器開發者工具或者其他外部工具來進行抓包,得到請求的URL、請求頭(request headers)以及請求的表單data資訊,這三樣恰恰是我們用Requests庫模擬POST請求時需要的。
關於請求頭的配置和GET請求是一樣的,都是定義headers
屬性即可。
而關於POST請求提交的引數,是和GET請求是不一樣的。
post請求四種傳送正文方式:
- (1)請求正文是
application/x-www-form-urlencoded
。 - (2)請求正文是
multipart/form-data
。 - (3)請求正文是
raw
。 - (4)請求正文是
binary
。
這四種提交資料的方式,是在請求頭Content-Type
屬性中來定義。
1、請求正文是application/x-www-form-urlencoded
Reqeusts支援以application/x-www-form-urlencoded
資料格式傳送POST請求(標準的POST請求資料格式,預設),只需要將請求的引數構造成一個字典,然後傳給requests.post()
的data引數即可。
示例:
"""
1.學習目標
必須掌握requests庫傳送post請求方法
2.HTTP協議中post請求引數型別
requests.post(url, data=None, json=None, **kwargs)
根據不同的請求引數型別分為如下幾種:
x-www-form-data-urlencoded
raw_json格式
form-data
binary
3.json格式
# 1.匯入requests庫
# 2.明確請求地址
# 3.明確請求引數
data = {key:value} 字典格式
# 4.傳送請求
requests.post(url=url,json=data)
4.需求
通過訪問http://httpbin.org/post介面,驗證post引數型別
"""
# 1.匯入requests庫
import requests
import json
# 2.明確請求地址
url = "http://httpbin.org/post"
# 3.明確請求引數
data = {
"dep_id": "T01",
"dep_name": "Test學院",
"master_name": "Test-Master",
"slogan": "Here is Slogan"
}
# 4.傳送請求
response = requests.post(url=url, data=data)
# 將python物件轉換為json字串(格式化返回資料)
result = json.dumps(response.json(), indent=2, ensure_ascii=False)
# print(type(result)) # 字串型別
print(result)
"""
返回結果:
{
"args": {},
"data": "",
"files": {},
****************主要看這裡
"form": {
"dep_id": "T01",
"dep_name": "Test學院",
"master_name": "Test-Master",
"slogan": "Here is Slogan"
},
***********************
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "88",
*****************主要看這裡
"Content-Type": "application/x-www-form-urlencoded",
*****************
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4",
"X-Amzn-Trace-Id": "Root=1-5ff401e3-1553596b7788e77e275c4772"
},
"json": null,
"origin": "106.35.9.12",
"url": "http://httpbin.org/post"
}
"""
說明:
- 傳送的請求中,form屬性接收了引數。
- 在請求頭中,
Content-Type
屬性為application/x-www-form-urlencoded
- 使用
application/x-www-form-urlencoded
格式傳送資料,requests.post(url=url, data=data)
方法中一定要使用data變數來接收引數。 - 換句話說資料格式是字典格式,使用data變數來接收,會預設傳送
application/x-www-form-urlencoded
資料格式的POST請求。(也可以在請求頭中明確一下Content-Type
屬性,但沒必要。)
2、請求正文是raw
RAW的原意就是“未經加工”。換句話說RAW方式使用的是純字串的資料上傳方式,所以在傳送POST請求之前,可能需要手工的把一些JSON格式的資料轉換成字串的(加兩單引號),在進行提交。
RAW資料格式的POST請求有兩種:
- 一種是xml格式文字(
text/xml
)。 - 一種是json格式文字(
application/json
)。
(1)json格式文字(application/json)
# 1.匯入requests庫
import requests
import json
# 2.明確請求地址
url = "http://httpbin.org/post"
# 3.明確請求引數
data = {
"data": [
{
"dep_id": "T01",
"dep_name": "Test學院",
"master_name": "Test-Master",
"slogan": "Here is Slogan"
}
]
}
# headers = {"Content-Type": "application/json"}
# 4.傳送請求
response = requests.post(url=url, json=data)
print(response) # <Response [200]>
print(response.text)
"""
返回結果:
{
"args": {},
"data": "{\"data\": [{\"dep_id\": \"T01\", \"dep_name\": \"Test\\u5b66\\u9662\", \"master_name\": \"Test-Master\", \"slogan\": \"Here is Slogan\"}]}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "119",
**************************主要看這裡
"Content-Type": "application/json",
**************************
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4",
"X-Amzn-Trace-Id": "Root=1-5ff40a9d-6a6f19d272ba4c1b40ff7bbb"
},
**************************主要看這裡
"json": {
"data": [
{
"dep_id": "T01",
"dep_name": "Test\u5b66\u9662",
"master_name": "Test-Master",
"slogan": "Here is Slogan"
}
]
},
**************************
"origin": "106.35.9.12",
"url": "http://httpbin.org/post"
}
"""
說明:
- 傳送的請求中,json屬性接收了引數。
- 在請求頭中,
Content-Type
屬性為application/json
。 - 使用
application/json
格式傳送資料,requests.post(url=url, json=data)
方法中一定要使用json變數來接收引數。 - 換句話說資料格式是Json格式,使用json變數來接收,Requests會預設傳送
application/json
資料格式的POST請求。(也可以在請求頭中明確一下Content-Type
屬性,但沒必要。)
注意:
這裡我們可以發現Requests模擬post請求時,請求頭格式為application/x-www-form-urlencoded與application/json的主要差別在於請求主體的構造格式(前者是鍵值對,後者是JSON串),前者直接用字典傳入,後者用json.dumps()函式將字典轉為JSON串即可。
也就是說在有需要的時候json模組下的dumps函式可以將dict轉換為str。
(2)xml格式文字(text/xml)
# 1.匯入requests庫
import requests
import json
# 2.明確請求地址
url = "http://httpbin.org/post"
# 3.明確請求引數
data = '<sites>' \
'<site>' \
'<name>菜鳥教程</name>' \
'<url>www.runoob.com</url>' \
'</site>' \
'<site>' \
'<name>Google</name>' \
'<url>www.google.com</url>' \
'</site>' \
'</sites>'
# requests.post方法中適用json變數來接收資料,
# 預設是"Content-Type": "application/json",
# 這裡我們需要重新宣告一下Content-Type屬性。
headers = {'Content-type': 'text/xml'}
# 4.傳送請求
# 如果資料用data變數來接收會報錯。
response = requests.post(url=url, json=data, headers=headers)
print(response) # <Response [200]>
# print(response.text)
# 將python物件轉換為json字串(格式化返回資料)
result = json.dumps(response.json(), indent=2, ensure_ascii=False)
# print(type(result)) # 字串型別
print(result)
"""
返回結果:
{
"args": {},
"data": "\"<sites><site><name>\\u83dc\\u9e1f\\u6559\\u7a0b</name><url>www.runoob.com</url></site><site><name>Google</name><url>www.google.com</url></site></sites>\"",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "149",
**************************主要看這裡
"Content-Type": "text/xml",
**************************
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4",
"X-Amzn-Trace-Id": "Root=1-5ff40fa5-21a79b532b1ccf6d20173fd7"
},
**************************主要看這裡
"json": "<sites><site><name>菜鳥教程</name><url>www.runoob.com</url></site><site><name>Google</name><url>www.google.com</url></site></sites>",
**************************
"origin": "106.35.9.12",
"url": "http://httpbin.org/post"
}
"""
說明:
- text/xml格式相對用的少。
- xml也可以作為一個檔案來傳輸。
- 需要重新宣告請求頭中
Content-Type
屬性。 - 其他和
application/json
一樣。
提示:其實raw格式資料可以上傳text、json、xml、html等純字元的文字。
3、正文是binary
使用binary格式的正文傳送POST請求,是直接使用二進位制流進行資料傳輸,多用於上傳單個圖片或圖片。
也可以用於把請求的引數放入一個檔案中,進行資料的提交。
示例如下:
"""
1.學習目標
掌握requests傳送post請求
2.HTTP協議中post請求引數型別
x-www-form-data-urlencoded
raw_json格式
form-data
binary
3.binary格式
# 1.明確請求地址
# 2.明確請求引數
data = {"files":open("檔名","rb")} 字典格式
# 3.傳送請求
requests.post(url= url,files=data)
4.需求
http://httpbin.org/post
"""
# 1.匯入requests
import requests
# 2.請求地址
url = "http://httpbin.org/post"
# 3.請求引數
# 讀取檔案中的資料作為引數進行提交。
# key位置要寫files,是規範
# 也可以寫其他的名字,不規範
data = {"files": open("test.txt", "rb")}
# 4.傳送請求
response = requests.post(url=url, files=data)
print(response.text)
"""
請求結果如下:
{
"args": {},
"data": "",
**************************主要看這裡
"files": {
"files": "username=\u5927\u5c0f\u59d0\r\npassword=test123456\r\nage=18"
},
**************************
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "192",
**************************主要看這裡
"Content-Type": "multipart/form-data; boundary=351e0b73ea144694a9e9fdd1e10d2486",
**************************
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4",
"X-Amzn-Trace-Id": "Root=1-5ff499ea-7ad42c4e6f056b44347b3c26"
},
"json": null,
"origin": "106.35.9.12",
"url": "http://httpbin.org/post"
}
"""
說明:
- 傳送的請求中,files屬性接收了引數。
- 在請求頭中,
Content-Type
屬性為multipart/form-data
。 - 使用
application/json
格式傳送資料,requests.post(url=url, files=data)
方法中一定要使用files變數來接收引數。 - 換句話說Requests也支援傳送binary資料形式的POST請求,只需將檔案傳給
requests.post()
方法的files
引數即可。
4、請求正文是multipart/form-data
multipart/form-data
資料格式的POST請求,多用於檔案上傳。
示例1:上傳檔案
"""
1.學習目標
掌握requests傳送post請求
2.HTTP協議中post請求引數型別
x-www-form-data-urlencoded
raw_json格式
form-data
binary
3.form-data格式
使用files變數來接收資料,預設是使用form-data格式傳送POST請求。
4.需求
http://httpbin.org/post
"""
import requests
files = {'file1': open('logo.png', 'rb')}
response = requests.post('http://127.0.0.1:9999/post', files=files)
print(response.text)
"""
介面返回結果:
{
"args": {},
"data": "",
**************************主要看這裡
"files": {
"file1": "data:application/octet-stream;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHerOCtwJPHpvQjoYqxmHighE/wO1YuuATgOKt9wGMd653WXlhe2xbcpauJjePjQYuZTOOk032eaYj+GgOQ+E1QCBj4UxtunNUFIjBmm5P05oBjLv99qoKgEpW9PSu1b0tAglXYOr2/uN4rtp6ZZay53n81IAlauN/pRH/2Q=="
},
**************************
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Content-Length": "394145",
**************************主要看這裡
"Content-Type": "multipart/form-data; boundary=4efea05a2cf34e78a75508a1ebf000ec",
**************************
"Host": "127.0.0.1:9999",
"User-Agent": "python-requests/2.18.4"
},
"json": null,
"origin": "127.0.0.1",
"url": "http://127.0.0.1:9999/post"
}
"""
示例2:上傳檔案並重新命名
我們也可以顯式地設定檔名,檔案型別和請求頭:
import requests
# hangge.png 為圖片名稱
files = {'file1': ('hangge.png', open('logo.png', 'rb'), 'image/png', {'Expires': '0'})}
response = requests.post('http://127.0.0.1:9999/post', files=files)
print(response.text)
"""
介面返回結果:
{
"args": {},
"data": "",
**************************主要看這裡
"files": {
"file1": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyacMkc0Yyc0UAf/Z"
},
**************************
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Content-Length": "7063",
**************************主要看這裡
"Content-Type": "multipart/form-data; boundary=382e06cba6834118a1f1efd0ea2c45e3",
**************************
"Host": "127.0.0.1:9999",
"User-Agent": "python-requests/2.18.4"
},
"json": null,
"origin": "127.0.0.1",
"url": "http://127.0.0.1:9999/post"
}
"""
示例3:多檔案上傳
有時我們需要在一個請求中同時傳送多個檔案,同樣使用 files 引數傳入一個陣列即可:
import requests
files = [
('file1', ('1.png', open('logo.png', 'rb'), 'image/png')),
('file2', ('2.png', open('logo.png', 'rb'), 'image/png'))
]
response = requests.post('http://127.0.0.1:9999/post', files=files)
print(response.text)
"""
介面返回結果:
{
"args": {},
"data": "",
**************************主要看這裡
"files": {
"file1": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgc3p8zdacMkc0Yyc0UAf/Z",
"file2": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgc3p8zdacMkc0Yyc0UAf/Z"
},
**************************
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Content-Length": "14054",
**************************主要看這裡
"Content-Type": "multipart/form-data; boundary=ba662835a2364b069c99ba3ffa56b974",
**************************
"Host": "127.0.0.1:9999",
"User-Agent": "python-requests/2.18.4"
},
"json": null,
"origin": "127.0.0.1",
"url": "http://127.0.0.1:9999/post"
}
"""
示例4:上傳時附帶其它引數
如果我們需要在上傳檔案的同時傳遞一些其它引數,也是可以的:
import requests
data = {
"name": "ABC.com",
"age": 100
}
files = [
('file1', ('1.png', open('logo.png', 'rb'), 'image/png')),
('file2', ('2.png', open('logo.png', 'rb'), 'image/png'))
]
response = requests.post('http://127.0.0.1:9999/post', data=data, files=files)
print(response.text)
"""
介面返回結果:
{
"args": {},
"data": "",
**************************主要看這裡
"files": {
"file1": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDA0Yyc0UAf/Z",
"file2": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDA0Yyc0UAf/Z"
},
"form": {
"age": "100",
"name": "ABC.com"
},
**************************
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Connection": "keep-alive",
"Content-Length": "14233",
**************************主要看這裡
"Content-Type": "multipart/form-data; boundary=6bdedbde2b48465683ef4e3451f7e015",
**************************
"Host": "127.0.0.1:9999",
"User-Agent": "python-requests/2.18.4"
},
"json": null,
"origin": "127.0.0.1",
"url": "http://127.0.0.1:9999/post"
}
"""
示例5:流式上傳檔案
-
有時我們需要上傳一個非常大的檔案(比如 1G 左右),如果像上面的方式直接使用 Requests 提交,可能會造成記憶體不足而崩潰。
-
所以傳送大檔案時還是建議將請求做成資料流。不過預設下 Requests 不支援流式上傳,但有個第三方包 requests-toolbelt 是支援的(本質還是 multipart/form-data 上傳)
-
在使用 requests-toolbelt 之前,我們首先通過 pip 進行安裝:
# cmd命令列終端執行如下命令。 pip install requests-toolbelt
示例如下:
"""
1.學習目標
掌握requests傳送post請求
2.HTTP協議中post請求引數型別
x-www-form-data-urlencoded
raw_json格式
form-data
binary
3.form-data格式
# 1.匯入requests庫,requests_toolbelt庫
# 2.明確請求地址
# 3.明確請求引數
data = {} 字典格式
對請求引數加工(例項化)
m = MultipartEncoder(fields = data)
# 4.新增請求頭
headers = {"Content_Type":m.content_type}
# 5.傳送請求
requests.post(url= url,data=m,headers=headers)
4.需求
http://httpbin.org/post
"""
# 1.匯入requests庫
import requests
from requests_toolbelt import MultipartEncoder
# from requests_toolbelt.multipart.encoder import MultipartEncoder
# 2.明確請求地址
url = "http://httpbin.org/post"
# 3.明確請求引數
data = {
"username": "Jerry",
"password": "1232456",
"sex": "男"
}
# requests-toolbelt 還提供了個監視器(MultipartEncoderMonitor),
# 該監視器接受一個回撥函式,我們可以在回撥中實時跟蹤進度。
# from requests_toolbelt import MultipartEncoderMonitor
# def my_callback(monitor):
# progress = (monitor.bytes_read / monitor.len) * 100
# print("\r 檔案上傳進度:%d%%(%d/%d)"
# % (progress, monitor.bytes_read, monitor.len), end=" ")
# m = MultipartEncoder(
# fields={'name': 'ABC.com', "age": '100',
# 'file1': ('1.png', open('logo.png', 'rb'), 'image/png'),
# 'file2': ('2.png', open('logo.png', 'rb'), 'image/png')}
# )
# 4.新增請求頭和加工請求引數
# 加工請求引數----讓每個引數都要帶有邊界
m = MultipartEncoder(fields=data)
# 新增請求頭
headers = {"Content_Type": m.content_type}
# 4.傳送請求
response = requests.post(url=url, data=m, headers=headers)
print(response.text)
"""
請求結果:
{
"args": {},
"data": "",
"files": {},
**************************主要看這裡
"form": {
"username": "Jerry",
"password": "1232456",
"sex": "男"
},
**************************
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "192",
**************************主要看這裡
"Content-Type": "multipart/form-data; boundary=351e0b73ea144694a9e9fdd1e10d2486",
**************************
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4",
"X-Amzn-Trace-Id": "Root=1-5ff499ea-7ad42c4e6f056b44347b3c26"
},
"json": null,
"origin": "106.35.9.12",
"url": "http://httpbin.org/post"
}
"""
5、總結Binary和Form-data區別
主要區別在於:
- Binary只可以上傳二進位制資料,通常用來上傳檔案,由於沒有鍵值,所以一次只能上傳一個檔案,而Form-data可以傳多個。
- Form-data既可以上傳檔案等二進位制資料,也可以上傳表單鍵值對。利用key-value對,可以分別對每個檔案進行描述。