一、簡介
HTTP協議規定post提交的數據必須放在消息主體(entity-body)中,但協議沒有規定數據必須使用什么編碼方式。HTTP協議是以ASCII碼傳輸,建立再TCP/IP協議之上的應用層規范。HTTP請求分為3個部分:狀態行、請求頭和消息主體。類似於:
<method> <request-URL> <version> <headers> <entity-body>
服務端通常是根據請求頭(header)中的Content_Type字段來獲取請求中的消息主體是用何種方式編碼,再對消息主體進行解析。
二、瀏覽器form表單提交
1.form表單常用屬性如下:
action:url 地址,服務器接收表單數據的地址 method:提交服務器的http方法,一般為post和get name: enctype: 表單數據提交時使用的編碼類型,默認使用"application/x-www-form-urlencoded",如果是使用POST請求,則請求頭中的content-type指定值就是該值。如果表單中有上傳文件,編碼類型需要使用"multipart/form-data",類型,才能完成傳遞文件數據。
PS:enctype為form表單數據的編碼格式,Content-type為HTTP傳輸的數據的編碼格式,要分清兩者!!!
2.瀏覽器提交表單時,會執行如下步驟:
① 識別出表單中表單元素的有效項,作為提交項
② 構建一個表單數據集
③ 根據form表單中enctype屬性的值作為content-type屬性的值作為content-type對數據進行編碼
④ 根據form表單中的action屬性和method屬性向指定的url地址發送數據
3.提交方式的不同
① get:表單數據會被encodeURIComponent后以參數的形式:name1=value1&name2=value2附帶在url?后面,再發送給服務器,並在url中顯示出來。
② post:enctype默認“application/x-www-form-urlencoded”對表單數據進行編碼,數據以鍵值對在http請求中發送給服務器;如果enctype屬性為“multipart/form-data”,則以消息的形式發送給服務器。
三、常見的四種編碼方式
1.application/x-www-form-urlencoded
最常見的post提交數據的編碼方式。瀏覽器的原生form表單,若不設置enctype屬性,默認以application/x-www-form-urlencoded編碼方式提交數據。for example:
POST http://www.example.com HTTP/1.1
Content-Type:application/x-www-form-urlencoded;charset=utf-8 title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
2.multipart/form-data
除了傳統的application/x-www-form-urlencoded表單,另一個常用的是上傳文件用的表單,其表單類型為multipart/form-data. for example:
<form action="/upload" enctype="multipart/form-data" method="post"> Username: <input type="text" name="username"> Password: <input type="password" name="password"> File: <input type="file" name="file"> <input type="submit"> </form>
3.application/json
4.text/xml
四、post請求四種傳送正文方式
1.請求正文是application/x-www-form-urlencoded
形式:requests.post(url='',data={'key1':'value1','key2':'value2'},headers={'Content-Type':'multipart/form-data'})
requests支持以form表單形式發送post請求,只需要將請求的參數構造成一個字典,然后傳給requests.post()的data
參數即可
import requests url = "http://httpbin.org/post" data = {"key1":"value1","key2":"value2"} headers = {"Content-type":"application/x-www-form-urlencoded"} r = requests.post(url=url,data=data,headers=headers) print(r.text)
由上圖可以看到,請求頭中的Content-Type字段已設置為application/x-www-form-urlencoded,且data = {'key1': 'value1', 'key2': 'value2'}
以form表單的形式提交到服務端,服務端返回的form字段即是提交的數據。
2.請求正文是multipart/form-data
形式:
requests.post(url='',data={'key1':'value1','key2':'value2'},headers={'Content-Type':'multipart/form-data'})
from requests_toolbelt import MultipartEncoder import requests url="http://httpbin.org/post" m = MultipartEncoder(fields={"field0":"value","field1":"value"}) # 刪掉fields效果一樣 headers = {"Content-Type":m.content_type} r = requests.post(url=url,data = m,headers=headers) print(r.text)
3.請求正文是raw
形式:
① 傳入xml格式文本(可擴展性語言:Extensible markup language)
requests.post(url='',data='<?xml ?>',headers={'Content-Type':'text/xml'})
② 傳入json格式文本
requests.post(url='',data=json.dumps({'key1':'value1','key2':'value2'}),headers={'Content-Type':'application/json'})
或:requests.post(url='',json={{'key1':'value1','key2':'value2'}},headers={'Content-Type':'application/json'})
for example:
import requests import json url = "http://httpbin.org/post" j = {"key1":"value1","key2":"value2"} data = json.dumps(j) # json模塊下的dumps函數將dict轉換為str headers = {"Content-type":"application/json"} r = requests.post(url=url,data=data,json=j,headers=headers) print(r.text)
PS:腳本中dumps不要寫成dump,否則會報缺失fp(類文件指針)的錯誤
python中json.dumps()和json.dump()的區別: https://www.cnblogs.com/fengff/p/11008353.html
4.請求正文是binary
形式:
requests.post(url='',files={'file':open('test.xls','rb')},headers={'Content-Type':'binary'})
import requests url = "http://httpbin.org/post" files = {"file":open("test.xlsx","rb")} headers = {"Content-type":"binary"} r = requests.post(url=url,files=files,headers=headers) print(r.text)
另外,requests也支持multipart方式發送post請求,只需將一文件傳給requests.post()的參數files即可。
import requests url = "http://httpbin.org/post" files = {"file":open("report.txt","rb")} r = requests.post(url=url,files=files) print(r.text)
PS:為了避免文件路徑的問題,建議文件直接放在當前py文件的同一級目錄下。