使用Python發(fā)送Post請求以及解析響應結果
一、Post請求
1、使用python發(fā)送一個Post請求
有時候遇到請求url中有很多參數。
1.1 示例1
accounts和pwd請到http://shop-xo.hctestedu.com/注冊。
import requests # 請求體 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 只有php項目需要application和application_client_type # 寫法一, 在請求Url中帶上所有參數,application和application_client_type,用&隔開 response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login" "&application=app" "&applicaiton_client_type=weixin", json=data) # 輸出響應結果 print(response.text)
執(zhí)行結果:
{"msg":"登錄成功","code":0,"data":{"id":"7073","username":"xx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"189","locking_integral":"0","referrer":"0","add_time":"1646195490","add_time_text":"2022-03-02 12:31:30","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxxx"}}
1.2 示例2
使用不定長參數 params,將url中需要的參數單獨封裝。
import requests # 請求體 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 使用不定長參數params param_data = { "application": "app", "application_client_type": "weixin" } # 寫法2:使用不定長參數params response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login", params=param_data, json=data) # 輸出響應結果 print(response.text)
執(zhí)行結果:
{"msg":"登錄成功","code":0,"data":{"id":"22299","username":"xx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxx"}}
二、獲取Response body
1、response.text
用type()查看response.text的類型,是str
import requests # 請求體 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 使用不定長參數params param_data = { "application": "app", "application_client_type": "weixin" } # 寫法2:使用不定長參數params response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login", params=param_data, json=data) # 輸出響應結果 print(response.text) print(type(response.text))
執(zhí)行結果:
{"msg":"登錄成功","code":0,"data":{"id":"22299","username":"xx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxx"}}
<class 'str'>
2、response.json()
用type()查看response.json()的類型,是dict
import requests # 請求體 data = { "accounts": "xx", "pwd": "xxx", "type": "username" } # 使用不定長參數params param_data = { "application": "app", "application_client_type": "weixin" } # 寫法2:使用不定長參數params response = requests.post(url="http://shop-xo.hctestedu.com/index.php?" "s=api/user/login", params=param_data, json=data) # 輸出響應結果 print(response.json()) print(type(response.json()))
執(zhí)行結果:
{"msg":"登錄成功","code":0,"data":{"id":"22299","username":"xx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xx","is_mandatory_bind_mobile":0,"token":"xxxxx"}}
<class 'dict'>
三、獲取響應狀態(tài)碼:res.status_code
print(response.status_code)
執(zhí)行結果:
200
更多狀態(tài)碼:
狀態(tài)代碼有三位數字組成,第一個數字定義了響應的類別,共分五種類別:
1xx:指示信息--表示請求已接收,繼續(xù)處理
2xx:成功--表示請求已被成功接收、理解、接受
3xx:重定向--要完成請求必須進行更進一步的操作
4xx:客戶端錯誤--請求有語法錯誤或請求無法實現
5xx:服務器端錯誤--服務器未能實現合法的請求常見狀態(tài)碼:
200 OK //客戶端請求成功
400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解
401 Unauthorized //請求未經授權,這個狀態(tài)代碼必須和WWW-Authenticate報頭域一起使用
403 Forbidden //服務器收到請求,但是拒絕提供服務
404 Not Found //請求資源不存在,eg:輸入了錯誤的URL
500 Internal Server Error //服務器發(fā)生不可預期的錯誤
503 Server Unavailable //服務器當前不能處理客戶端的請求,一段時間后可能恢復正常
四、獲取響應cookies:res.cookies
print(response.cookies)
執(zhí)行結果:
<RequestsCookieJar[<Cookie PHPSESSID=92ppj01t00t4v142rd8fsmos7k for shop-xo.hctestedu.com/>]>
五、獲取響應headers:res.headers
print(response.headers)
執(zhí)行結果:
{'Server': 'nginx', 'Date': 'Sun, 05 Mar 2023 10:04:02 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Set-Cookie': 'PHPSESSID=ul9qsgallg17d5am81q08pfhj0; path=/; HttpOnly', 'Expires': 'Thu, 19 Nov 1981 08:52:00 GMT', 'Cache-Control': 'no-store, no-cache, must-revalidate', 'Pragma': 'no-cache'}
六、獲取響應結果原始內容:res.content
content,沒有經過編譯的,以字節(jié)的形式展示。而上述提到的text是編譯過的。自動找到請求頭中的編碼格式,進行解析。
print(response.content) print(type(response.content))
執(zhí)行結果:
b'{"msg":"\xe7\x99\xbb\xe5\xbd\x95\xe6\x88\x90\xe5\x8a\x9f","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http:\\/\\/shop-xo.hctestedu.com\\/static\\/index\\/default\\/images\\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}}'<class 'bytes'>
content還支持手動的編碼,例如使用utf-8編碼,編碼后的是str類型,json本質是一種字符串類型
resp = response.content.decode("utf-8") print(resp) print(type(resp))
執(zhí)行結果:
{"msg":"登錄成功","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}}<class 'str'>
七、獲取響應結果:最原生的狀態(tài),對象在內存中的地址:res.raw
print(response.raw) print(type(response.raw))
執(zhí)行結果:
<urllib3.response.HTTPResponse object at 0x0000023317D8D880><class 'urllib3.response.HTTPResponse'>
八、解析響應數據
響應數據如下:
{ "msg": "登錄成功", "code": 0, "data": { "id": "22299", "username": "Summer", "nickname": "", "mobile": "", "email": "", "avatar": "http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg", "alipay_openid": "", "weixin_openid": "", "weixin_unionid": "", "weixin_web_openid": "", "baidu_openid": "", "toutiao_openid": "", "qq_openid": "", "qq_unionid": "", "integral": "0", "locking_integral": "0", "referrer": "0", "add_time": "1678005098", "add_time_text": "2023-03-05 16:31:38", "mobile_security": "", "email_security": "", "user_name_view": "chengcheng", "is_mandatory_bind_mobile": 0, "token": "d653d78ac417f65e1cd38c6f3e220341" } }
通常我們獲取響應數據后,是需要進行結果驗證的。例如,我想從登錄接口的響應中拿到token,供后面的接口請求鑒權使用。
1、字典方式解析及其缺點
上面已經講到,可以使用response.json()方法拿到一個字典。既然是字典,就可以用處理字典的方式來獲取某個字段的值。
resp = response.json() token = resp["data"]["token"] print(token )
執(zhí)行結果:
d653d78ac417f65e1cd38c6f3e220341
字典解析的缺點:如果接口數據異常,響應體缺少某個字段,就會發(fā)生keyerror,導致程序異常。
resp = response.json() token = resp["data"]["token1"] print(token )
執(zhí)行結果:
Traceback (most recent call last):
File "E:\Coding\python-workspace\Interface_test\first_requests.py", line 128, in <module>
token = resp["data"]["token1"]
KeyError: 'token1'
2、Jsonpath表達式解析及其優(yōu)點
上面的響應body結構比較簡單,如果我們要解析特別復雜的響應體,通過字典方式就很復雜。這個時候更推薦jsonpath。需要引入jsonpath庫。
import jsonpath resp = response.json() # 將返回值轉換成字典格式 token = jsonpath.jsonpath(resp, '$..token') # token的jsonpath表達式:$..token print(token)
執(zhí)行結果:
['d653d78ac417f65e1cd38c6f3e220341']
通過結果來看,獲取到的token是只有一個元素的列表。我們要想拿到token通過下標訪問。
修改上述代碼:
import jsonpath resp = response.json() # 將返回值轉換成字典格式 token = jsonpath.jsonpath(resp, '$..token') # token的jsonpath表達式:$..token print(token[0])
執(zhí)行結果:
d653d78ac417f65e1cd38c6f3e220341
Jsonpath表達式解析的優(yōu)點:如果響應體缺少某個字段,通過Jsonpath表達式解析不到結果,就會返回False,永遠不會發(fā)生異常。我們可根據返回結果進行后續(xù)處理。
import jsonpath resp = response.json() # 將返回值轉換成字典格式 # 使用錯誤的jsonpath表達式 token = jsonpath.jsonpath(resp, '$..token1') # token的jsonpath表達式:$..token1 if isinstance(token, List): print(f'可以解析到token,值為:{token[0]}') else: print(f'解析不到token,結果為:{token}') # 使用正確的jsonpath表達式 token = jsonpath.jsonpath(resp, '$..token') # token的jsonpath表達式:$..token if isinstance(token, List): print(f'可以解析到token,值為:{token[0]}') else: print(f'解析不到token,結果為:{token}')
執(zhí)行結果:
解析不到token,結果為:False
可以解析到token,值為:d653d78ac417f65e1cd38c6f3e220341
3、如何知道自己寫的jsonpath表達式是否正確呢?
jsonpath在線校驗工具:http://jsonpath.com/
將response粘貼在Inputs區(qū)域,在JSONPath區(qū)域輸入表達式,在Evaluation Results區(qū)域查看是否解析到期望的值。當解析不到值時,返回的是空列表(No match)
jsonpath表達式語法
九、獲取請求的信息
print(f'請求url:{response.request.url}') print(f'請求方法:{response.request.method}') print(f'請求Header:{response.request.headers}') print(f'請求路徑:{response.request.path_url}')
執(zhí)行結果:
請求url:http://shop-xo.hctestedu.com/index.php?s=api/user/login&application=app&application_client_type=weixin
請求方法:POST
請求Header:{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '69', 'Content-Type': 'application/json'}
請求路徑:/index.php?s=api/user/login&application=app&application_client_type=weixin
十、json=data 和 data=data 參數區(qū)別
接口電商項目后臺代碼(PHP)中,json=data以及data=data這2種參數類型都可以接收。在實際項目應用中,常見的報文格式是application/json。因此最常使用的是json=data
1、json=data
請求頭默認為:Content-Type=application/json
url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, json=data, params=param_data) # 查看請求中的請求頭信息,Content-Type=application/json print(res.request.headers) print(res.text)
執(zhí)行結果:
{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '69', 'Content-Type': 'application/json'}
{"msg":"登錄成功","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}}
2、data=data
請求頭默認為:application/x-www-form-urlencoded
url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, data=data, params=param_data) # 查看請求中的請求頭信息,Content-Type=application/x-www-form-urlencoded print(res.request.headers) print(res.text)
執(zhí)行結果:
{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '50', 'Content-Type': 'application/x-www-form-urlencoded'}
{"msg":"登錄成功","code":0,"data":{"id":"22299","username":"xxxxx","nickname":"","mobile":"","email":"","avatar":"http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg","alipay_openid":"","weixin_openid":"","weixin_unionid":"","weixin_web_openid":"","baidu_openid":"","toutiao_openid":"","qq_openid":"","qq_unionid":"","integral":"0","locking_integral":"0","referrer":"0","add_time":"1678005098","add_time_text":"2023-03-05 16:31:38","mobile_security":"","email_security":"","user_name_view":"xxxxx","is_mandatory_bind_mobile":0,"token":"d653d78ac417f65e1cd38c6f3e220341"}}
3、設置請求頭
如果是java項目,spring會將請求實體的內容自動轉換為Bean,但前提是請求的Content-Type必須設置為application/json
在請求頭中定義發(fā)送報文的格式
1、Content-Type: application/json
headers = { 'Content-Type': 'application/json' # 'Content-Type': 'application/x-www-form-urlencoded' } url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, params=param_data, json=data, headers=headers) print(res.request.headers)
執(zhí)行結果:
{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Content-Length': '50'}
2、Content-Type:application/x-www-form-urlencoded
headers = { # 'Content-Type': 'application/json' 'Content-Type': 'application/x-www-form-urlencoded' } url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, params=param_data, data=data, headers=headers) print(res.request.headers)
執(zhí)行結果:
{'User-Agent': 'python-requests/2.28.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '69'}
十一、Json和字典數據轉換
1、json.dumps(),將字典轉換成Json
使用json.dumps()可以將字典轉換成Json
test = { "msg": "登錄成功", "code": 0, "data": { "id": "22299", "username": "Summer", "nickname": "", "mobile": "", "email": "", "avatar": "http:\/\/shop-xo.hctestedu.com\/static\/index\/default\/images\/default-user-avatar.jpg", "alipay_openid": "", "weixin_openid": "", "weixin_unionid": "", "weixin_web_openid": "", "baidu_openid": "", "toutiao_openid": "", "qq_openid": "", "qq_unionid": "", "integral": "0", "locking_integral": "0", "referrer": "0", "add_time": "1678005098", "add_time_text": "2023-03-05 16:31:38", "mobile_security": "", "email_security": "", "user_name_view": "chengcheng", "is_mandatory_bind_mobile": 0, "token": "d653d78ac417f65e1cd38c6f3e220341" } } print(type(test)) print(json.dumps(test)) print(type(json.dumps(test)))
執(zhí)行結果:
<class 'dict'>
{"msg": "\u767b\u5f55\u6210\u529f", "code": 0, "data": {"id": "22299", "username": "Summer", "nickname": "", "mobile": "", "email": "", "avatar": "http:\\/\\/shop-xo.hctestedu.com\\/static\\/index\\/default\\/images\\/default-user-avatar.jpg", "alipay_openid": "", "weixin_openid": "", "weixin_unionid": "", "weixin_web_openid": "", "baidu_openid": "", "toutiao_openid": "", "qq_openid": "", "qq_unionid": "", "integral": "0", "locking_integral": "0", "referrer": "0", "add_time": "1678005098", "add_time_text": "2023-03-05 16:31:38", "mobile_security": "", "email_security": "", "user_name_view": "chengcheng", "is_mandatory_bind_mobile": 0, "token": "d653d78ac417f65e1cd38c6f3e220341"}}
<class 'str'>
2、json.loads(),將Json轉換成字典
使用json.loads()可以將Json轉換成字典
print(json.loads(json.dumps(test))) print(type(json.loads(json.dumps(test))))
執(zhí)行結果:
{'msg': '登錄成功', 'code': 0, 'data': {'id': '22299', 'username': 'Summer', 'nickname': '', 'mobile': '', 'email': '', 'avatar': 'http:\\/\\/shop-xo.hctestedu.com\\/static\\/index\\/default\\/images\\/default-user-avatar.jpg', 'alipay_openid': '', 'weixin_openid': '', 'weixin_unionid': '', 'weixin_web_openid': '', 'baidu_openid': '', 'toutiao_openid': '', 'qq_openid': '', 'qq_unionid': '', 'integral': '0', 'locking_integral': '0', 'referrer': '0', 'add_time': '1678005098', 'add_time_text': '2023-03-05 16:31:38', 'mobile_security': '', 'email_security': '', 'user_name_view': 'chengcheng', 'is_mandatory_bind_mobile': 0, 'token': 'd653d78ac417f65e1cd38c6f3e220341'}}
<class 'dict'>
3、json格式報文發(fā)送
方法一:參數是data,值:將字典data轉換成json
url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' headers = { 'Content-Type': 'application/json' } res = requests.post(url=url, data=json.dumps(data), headers=headers) print(res.text)
方法二:參數是json,值:字典data
url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, json=data) print(res.text) print(res.json()) print(type(res.json())) assert "登錄成功" == res.json()['msg']
十二、獲取接口響應時間
url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' res = requests.post(url=url, json=data) print(res.text) # 獲取接口響應時間,單位秒 print(r.elapsed.total_seconds())
執(zhí)行結果:
{"msg":"登錄成功","code":0,"data":{"body_html":""}}
0.078264
十三、接口調用失敗處理
同一個用例中有多個接口調用,一個接口調用失敗如何防止程序終止?
用于判斷接口請求的狀態(tài)碼是否為200,如果是,則返回none,如果不是則返回異常。
調用接口時結合try…except進行使用。
# 模擬接口404,使用不存在的request url: login1 url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login1' res = requests.post(url=url, json=data) try: assert 200 == res.status_code except: # 異常處理1:直接跳過,可繼續(xù)執(zhí)行后面代碼 # pass # 異常處理2:打印詳細異常信息 print(res.status_code) res.raise_for_status() else: print(res.text)
執(zhí)行結果:
404
Traceback (most recent call last):
File "E:\Coding\python-workspace\Interface_test\first_requests.py", line 220, in <module>
assert 200 == res.status_code
AssertionErrorDuring handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "E:\Coding\python-workspace\Interface_test\first_requests.py", line 226, in <module>
res.raise_for_status()
File "D:\Developer\Python\Python310\lib\site-packages\requests\models.py", line 1021, in raise_for_status
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: http://shop-xo.hctestedu.com/index.php?s=api/user/login1
十四、接口超時
url = 'http://shop-xo.hctestedu.com/index.php?s=api/user/login' try: res = requests.post(url=url, json=data, timeout=0.01) # timeout,單位秒 except (TimeoutError, ReadTimeout, ConnectTimeout): # ConnectTimeout:指的是建立連接所用的時間,適用于網絡狀況正常的情況下,兩端連接所用的時間。 # ReadTimeout:指的是建立連接后從服務器讀取到可用資源所用的時間。 print("發(fā)生錯誤,請稍后重試") else: # 獲取接口響應時間,單位秒 print(res.elapsed.total_seconds()) print(res.text)
執(zhí)行結果:
發(fā)生錯誤,請稍后重試
當把timeout改成0.1,執(zhí)行結果:
0.07419
{"msg":"登錄成功","code":0,"data":{"body_html":""}}
總結
到此這篇關于使用Python發(fā)送Post請求以及解析響應結果的文章就介紹到這了,更多相關Python發(fā)送Post請求內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python os.listdir與os.walk實現獲取路徑詳解
這篇文章主要介紹了Python使用os.listdir和os.walk獲取文件路徑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2022-10-10