前言
前幾天一個剛接觸Python不深的朋友問我的Python的xml格式Post請求怎么發送,剛好最近也在學習Http請求相關的內容,所以決定總結一下各類Post請求的Python實現。
Happy post man
這里說的各類Post請求主要包含json格式、xml格式、文件上傳(form-data)、及默認傳遞的urlencoded。在開始介紹相關的Python用法之前,我們首先我們來了解一下HTTP的報文結構。
HTTP的報文結構
上面這張圖是Fiddle捕獲的一個實際請求報文,它清晰的展示了HTTP 消息的結構。詳情如下:
- 請求行:即第一排用空格分割成的三個小塊,分別對應請求方法、請求URL、HTTP協議版本三個部分。
- 請求頭:從第二行開始到倒數第二行都是我們的請求頭(headers)。
- 消息主體:截圖的最后一行是請求體,也就是我們要發送的數據的主體,消息主體(entity-body)。
也就是說一個正常的post請求主要由請求行,請求頭,消息主體組成。接下來我們來了解一下什么是Content-Type。
Content-Type的定義
要了解Content-Type首先我們要先對HTTP/1.1 協議有一定的了解。
眾所周知,HTTP/1.1 規定的 HTTP 請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 8種,其中 POST 一般用來向服務端提交數據。
但是可能很多人不知道的是,雖然HTTP/1.1協議規定 了POST 提交的數據必須放在消息主體(entity-body)中,但並沒有規定數據必須使用什么樣的編碼方式。也就是說,開發者完全可以自己決定消息主體的格式。
但是數據除了請求方發送之外,還要服務端能夠解析才有意義。而這個解析操作的第一步通常就是是根據請求頭(headers)中的 Content-Type 字段來獲知請求中的消息主體的編碼方式,然后再對數據進行對應的解析操作。也就是說請求頭中的Content-Type字段用於規定請求體的編碼格式,服務端代碼需要使用它對接收到的消息主體進行解析。
Content-Type的格式種類
我們前面說了HTTP/1.1沒有規定協議編碼方式,但是隨着協議的應用推廣,已經慢慢的形成了四種最常用的編碼方式,基本上形成了相應的規范,即基本固定的Content-Type取值application/x-www-form-urlencoded(默認格式)、application/json、text/xml、multipart/form-data,與默認傳遞的urlencoded、json格式、xml格式、文件格式一 一對應。
接下來我們會每個編碼方式的應用場景及Python實現分別進行介紹。我們此次主要使用http://httpbin.org/來做演示。
httpbin是一個專門用來測試 HTTP 請求及響應的網站,其github開源地址是https://github.com/requests/httpbin。作者另外一個開源庫就是大名鼎鼎的requests,它也是我們演示代碼中重要的部分。
application/x-www-form-urlencoded格式
這是post請求最常見也是默認的數據提交格式。它要求數據名稱(name)和數據值(value)之間以等號相連,與另一組name/value值之間用&相連。例如:parameter1=12345¶meter2=23456。將請求的內容進行格式化了,其實這個方法同時簡化的客戶端發送,也簡化了服務器端獲取,服務器通過getParameters(String name)即可獲取到傳送來的信息。這是最常見post提交數據的方式,以form表單形式提交數據。
參考Python實現
import requests
datas = {"param1": "Detector", "param2": "cnblogs"}
r = requests.post("http://httpbin.org/post", data=datas)
print(r.text)
print(r.status_code)
我們在代碼中沒有進行Content-Type的設置,但是我們來看看Fiddler抓包的結果。
可以看到Content-Type已經被自動填充為application/x-www-form-urlencoded了。
application/json格式
application/json 這個 Content-Type 作為響應頭大家肯定不陌生。實際上,現在越來越多的人把它作為請求頭,用來告訴服務端消息主體是序列化后的 JSON 字符串。由於 JSON 規范的流行,除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會遇上什么麻煩。
參考Python實現
import json
import requests
headers = {'Content-Type': 'application/json'}
datas = json.dumps({"param1": "Detector", "param2": "cnblogs"})
r = requests.post("http://httpbin.org/post", data=datas, headers=headers)
print(r.text)
有興趣的朋友可以嘗試不添加請求頭,抓包看看結果。
Fiddler抓包結果
text/xml數據格式
它是一種使用 HTTP 作為傳輸協議,XML 作為編碼方式的遠程調用規范。典型的 XML-RPC(XML Remote Procedure Call) 請求數據是這樣的:
<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>
參考Python實現
import requests
headers = {"Content-Type": "text/xml"}
datas = """<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>"""
r = requests.post("http://httpbin.org/post", data=datas, headers=headers)
print(r.text)
可以看到,我們和application/json請求的區別是,我們把請求的內容換成了xml格式的字符串,Content-Type換成了text/xml。
Fiddler抓包結果
multipart/form-data數據格式
multipart/form-data主要用於文件上傳,當我們使用它時,必須讓 form表單的enctype 等於 multipart/form-data。直接來看一個請求示例,主要實現了上傳本地的test.txt文件:
參考Python實現
import requests
files = {"file": open("C:/Users/Administrator/Desktop/test.txt", "rb")}
r = requests.post("http://httpbin.org/post", files=files)
print(r.text)
Fiddler抓包結果
參考資料
https://www.cnblogs.com/aaronjs/p/4165049.html
https://blog.csdn.net/u010256388/article/details/68491509
https://www.jianshu.com/p/3c790e98ea8d
https://www.cnblogs.com/softidea/p/5745369.html
https://blog.csdn.net/qq_39640877/article/details/80951327