前言
說到python發送HTTP請求進行接口自動化測試,腦子裏第一個閃過的可能就是requests庫了,固然python有不少模塊能夠發送HTTP請求,包括原生的模塊http.client,urllib2等,但因爲原生的模塊過於複雜,使用繁瑣,那麼requests庫就誕生了,它也是現階段比較流行的接口自動化測試工具之一javascript
requests是個第三方庫,封裝了HTTP請求的全部方法,使用方便簡單,只須要根據不一樣的請求方式調用相對應的方法就能夠完成發送網絡請求的整個過程,那麼今天咱們就來講說requests庫是如何使用的,那麼在開始以前咱們大體說一下今天的主要內容:css
1. requets如何發送get請求html
2. requests如何發送post請求java
3. params參數和data參數的區別python
4. requests庫中Session類的的妙用jquery
5. 針對get請求和post請求,對requests進行簡單封裝linux
安裝
一般,咱們使用第三方庫以前,都須要先進行安裝編程
cmd執行命令 pip install requests 接着就能夠引入該模塊使用其提供的方法了json
import requestsapi
發送get請求
requests是經過調用get()方法來完成發送get請求的,那麼,在掌握requests庫如何發送get請求以前,你還應該簡單瞭解一下什麼是get請求,你能夠參照這篇文章https://www.cnblogs.com/linuxchao/p/linuxchao-http.html
一般在咱們學習一個方法如何使用以前,咱們需先知道這個方法須要哪些參數?參數類型是什麼? 那麼咱們就先分析一下get()方法的源碼
1 def get(url, params=None, **kwargs): 2 r"""Sends a GET request. 3 4 :param url: URL for the new :class:`Request` object. 5 :param params: (optional) Dictionary, list of tuples or bytes to send 6 in the body of the :class:`Request`. 7 :param \*\*kwargs: Optional arguments that ``request`` takes. 8 :return: :class:`Response <Response>` object 9 :rtype: requests.Response 10 """ 11 12 kwargs.setdefault('allow_redirects', True) 13 return request('get', url, params=params, **kwargs)
這就是get方法的源碼了,你應該可以發現,get()方法只有一個必傳的參數url,其餘參數都是非必傳的,那麼其餘的參數有什麼做用呢?
params
對於這個參數,能夠是字典,也能夠是嵌套元組的列表,基於get請求的特色,請求參數是能夠直接跟在URL以後的,以?號開始以key=value的形式傳遞(多個參數使用&符號進行分割),可是爲了明確區分URL和參數,就須要使用params參數傳遞
**kwargs:其餘一些關鍵字參數,暫時不作介紹
接下來咱們來看2個簡單的實例,體會一下reauets經過get()方法發送一個不帶參數的get請求和帶參數的請求的過程
經過get()方法發送get請求訪問博客園首頁
""" ------------------------------------ @Time : 2019/7/11 20:34 @Auth : linux超 @File : requests_blog.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ import requests # 導入requests模塊 response = requests.get('https://www.cnblogs.com/') # 發送get請求 print(response.text) # 獲取響應數據
響應數據
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="referrer" content="always" /> <title>博客園 - 代碼改變世界</title> <meta name="keywords" content="開發者,博客園,開發者,程序猿,程序媛,極客,編程,代碼,開源,IT網站,Developer,Programmer,Coder,Geek,技術社區" /> <meta name="description" content="博客園是一個面向開發者的知識分享社區。自建立以來,博客園一直致力並專一於爲開發者打造一個純淨的技術交流社區,推進並幫助開發者經過互聯網分享知識,從而讓更多開發者從中受益。博客園的使命是幫助開發者用代碼改變世界。" /> <link rel="shortcut icon" href="//common.cnblogs.com/favicon.ico" type="image/x-icon" /> <link rel="Stylesheet" type="text/css" href="/bundles/aggsite.css?v=IlEZk4Ic2eCzcO6r0s4bGm62FAo8VZI-US_0EqUe2Bk1" /> <link id="RSSLink" title="RSS" type="application/rss+xml" rel="alternate" href="http://feed.cnblogs.com/blog/sitehome/rss" /> <script src="//common.cnblogs.com/scripts/jquery-2.2.0.min.js" type="text/javascript"></script> <script src="/bundles/aggsite.js?v=cE0bqImLWsEG3gZXOupKxj5tj_ukK7pLeSd73DHZOT81" type="text/javascript"></script> <script async='async' src='https://www.googletagservices.com/tag/js/gpt.js'></script> <script> var googletag = googletag || {}; googletag.cmd = googletag.cmd || []; </script>
這裏我只截取了一部分響應數據,響應數據實際上是博客園的首頁HTML源碼
能夠看到只須要一行代碼便可完成整個請求過程,經過response.text獲得響應數據(其實這個過程和咱們在瀏覽器中輸入博客園地址訪問是同樣的),固然你還可使用如下的方法獲取不一樣的響應數據
response.headers # 獲取響應頭信息 response.cookies # 獲取返回的cookie response.status_code # 獲取狀態碼
發送帶params參數的get請求
""" ------------------------------------ @Time : 2019/7/11 20:34 @Auth : linux超 @File : requests_blog.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ import requests login_url = r'http://***/futureloan/mvc/api/member/login' # 接口地址 login_data = {"mobilephone": "13691579841", "pwd": 123456} # 接口所需參數 response = requests.get(url=login_url, params=login_data) # 發送get請求 print(response.text) # 獲取響應數據
print(response.url)
響應數據
{"status":1,"code":"10001","data":null,"msg":"登陸成功"} http://***/futureloan/mvc/api/member/login?mobilephone=13691579841&pwd=123456 Process finished with exit code 0
咱們經過傳遞一個字典給params參數,便可完成帶參數的get請求,並獲取響應數據
注意
1.咱們平常工做中也最好傳遞字典做爲接口數據,若是數據類型是json則在發送請求的時候須要先轉成字典
2.只要你發送的是get請求,且不想經過url拼接的方式直接傳遞接口參數,那麼只能使用params參數來傳遞(若是你使用data,json等參數時你會發現,請求並不會成功),由於經過params傳遞的參數會附加到url後,這也是get請求的特色,所以你需記住:發送get請求時參數只能使用params便可
以上只是簡單的發送get請求的方法,至於如何發送帶其餘參數的get請求(好比headers,cookies等),還需對get()進一步的研究和實踐
發送post請求
一樣,在開始學習下面的內容以前,仍建議你先了解什麼是post請求及其特色,對你學習接下來的內容也會更好理解https://www.cnblogs.com/linuxchao/p/linuxchao-http.html
requests發送post請求是經過post()方法來實現的,那麼咱們仍是先看一下它的源碼
1 def post(url, data=None, json=None, **kwargs): 2 r"""Sends a POST request. 3 4 :param url: URL for the new :class:`Request` object. 5 :param data: (optional) Dictionary (will be form-encoded), bytes, or file-like object to send in the body of the :class:`Request`. 6 :param json: (optional) json data to send in the body of the :class:`Request`. 7 :param \*\*kwargs: Optional arguments that ``request`` takes. 8 :return: :class:`Response <Response>` object 9 :rtype: requests.Response 10 """ 11 12 return request('post', url, data=data, json=json, **kwargs)
經過源碼咱們能夠發現,post()和get()同樣,僅有一個url參數是必傳的,其餘仍然能夠不傳遞,可是其中data和json參數倒是post()方法中最重要的參數,下面就說一下什麼時候使用data,什麼時候使用json
data
大多數post請求的接口默認支持參數類型Content-Type爲application/x-www-form-urlencoded, 它告訴咱們請求的接口參數須要傳遞一個form表單,那麼咱們每每是經過構造一個字典來傳遞form表單的,
因此當咱們向服務器提交form表單時就可使用data參數,它會接收一個字典類型的數據,存放到請求體中,而後發送給服務器(參數需是字典類型)
json
首先你訪問的接口須要支持content_type爲application/json格式的數據類型,那麼你就能夠經過json這個參數來傳遞接口參數(參數能夠是字典也能夠是json類型)
下面咱們來看一個發送post請求,使用data參數的實例
""" ------------------------------------ @Time : 2019/7/12 10:22 @Auth : linux超 @File : requests_blog.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ import requests login_url = r'http://***/futureloan/mvc/api/member/login' # 接口地址 login_data = {"mobilephone": "13691579841", "pwd": 123456} # 接口所需參數 response = requests.post(url=login_url, data=login_data) # 發送post請求 print(response.text) # 獲取響應數據 print(response.url) print(response.status_code)
響應數據
{"status":1,"code":"10001","data":null,"msg":"登陸成功"} http://***:8080/futureloan/mvc/api/member/login 200 Process finished with exit code 0
使用json參數實例
""" ------------------------------------ @Time : 2019/7/12 10:22 @Auth : linux超 @File : requests_blog.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ import requests login_url = r'http://***/futureloan/mvc/api/member/login' # 接口地址 login_data = {"mobilephone": "13691579841", "pwd": 123456} # 接口所需參數 response = requests.post(url=login_url, json=login_data) # 發送post請求 print(response.text) # 獲取響應數據 print(response.url) print(response.status_code)
響應數據
{"status":0,"code":"20103","data":null,"msg":"手機號不能爲空"} http://***/futureloan/mvc/api/member/login 200 Process finished with exit code 0
能夠看到使用data參數和json參數,獲取到的返回結果是不同的,由於我這裏使用的接口不支持application/json數據格式,因此當你使用json參數傳遞參數時,服務器是沒法解析數據的,也就不會返回正確的結果了
因此對於什麼時候使用data參數,什麼時候使用json參數,還須要根據實際的接口所支持的數據類型進行選擇
params和data區別
上面已經說過get請求中的params參數和post請求中的data參數,那麼這兩個參數到底有什麼區別呢?
1. 發送get請求時,因爲get請求沒有請求體,請求參數只能跟在url地址後的,並且服務器也只能經過解析url得到請求的參數,所以get()方法發送get請求時只能使用params參數,它會把請求的參數默認追加到url地址後面
2. 一般狀況下用戶須要提交某些數據時,發送的請求通常都爲post請求,post請求會提交一個form表單,那麼咱們就能夠構造一個字典格式的數據,使用data參數傳遞,因爲post請求是有請求體的,並且請求參數就存放在請求體中,服務器也只能經過解析請求體中內容而得到請求的參數,因此post請求不能使用params傳遞接口參數,只能使用data,json,file等, data參數會把請求參數放到請求體中
Session類的妙用
實際工做中,咱們會常常遇到須要保持某一個狀態,才能測試後續的接口,好比說:充值接口,那麼須要用戶先登陸,且一直保持登陸狀態才能進行充值,那麼對於這種狀況該怎麼解決呢?這就要用到requests庫中的Session類了,Session能夠保持請求的狀態,像咱們訪問某個網站同樣,咱們只要登陸後就能夠瀏覽該網站上的任意頁面,先看下面實例
""" ------------------------------------ @Time : 2019/7/12 10:22 @Auth : linux超 @File : requests_blog.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ import requests login_url = r'http://***/futureloan/mvc/api/member/login' # 登陸接口地址 login_data = {"mobilephone": "13691579841", "pwd": 123456} # 接口所需參數 response_login = requests.post(url=login_url, data=login_data) # 發送post請求 登陸 print(response_login.text) recharge_url = r'http://***/futureloan/mvc/api/member/recharge' # 充值接口地址 recharge_data = {"mobilephone": "13691579841", "amount": 10000.00} # 接口所需參數 response_recharge = requests.post(url=recharge_url, data=recharge_data) # 發送請求,開始充值 print(response_recharge.text)
執行結果
{"status":1,"code":"10001","data":null,"msg":"登陸成功"} {"status":0,"code":null,"data":null,"msg":"抱歉,請先登陸。"} Process finished with exit code 0
能夠發現,咱們以前都已經登陸過了,可是充值時卻失敗了,緣由就是直接使用reauests來發送請求時,並不會保持當前的狀態(這也是HTTP請求的缺陷),如今咱們使用Session對像再次發送充值請求,修改代碼
""" ------------------------------------ @Time : 2019/7/12 10:22 @Auth : linux超 @File : requests_blog.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ import requests request = requests.Session() # 初始化Session login_url = r'http://***/futureloan/mvc/api/member/login' # 登陸接口地址 login_data = {"mobilephone": "13691579841", "pwd": 123456} # 接口所需參數 response_login = request.request(method='post', url=login_url, data=login_data) # 發送post請求 登陸 print(response_login.text) recharge_url = r'http://***/futureloan/mvc/api/member/recharge' # 充值接口地址 recharge_data = {"mobilephone": "13691579841", "amount": 10000.00} # 接口所需參數 response_recharge = request.request(method='post', url=recharge_url, data=recharge_data) # 發送請求,開始充值 print(response_recharge.text)
執行結果
{"status":1,"code":"10001","data":null,"msg":"登陸成功"} {"status":1,"code":"10001","data":
{"id":5451,"regname":"test","pwd":"E10ADC3949BA59ABBE56E057F20F883E","mobilephone":"13691579841","leaveamount":"15000.00","type":"1","regtime":"2019-05-26 19:08:44.0"},
"msg":"充值成功"} Process finished with exit code 0
能夠發現,咱們改用Session對象來發送充值請求就成功了。那這是什麼緣由呢?
簡單來講,當咱們第一次請求服務器時,獲取的響應信息會包含一個set-cookie的字段,保存了咱們登陸的cookies信息,若是咱們想保持這個狀態,那麼再次訪問服務器時就須要帶上這個cookies傳遞給服務器,才能保持這個狀態。
那麼咱們使用Session對象發送請求時,Session會自動幫咱們完成上述的過程,Session會自動把cookies的信息傳遞給服務器,而無需咱們在請求參數中手動添加cookies,這樣就保持了登陸的狀態,後續的依賴操做均可以正常執行了
reqests簡單封裝
有人會問,requests庫已經封裝的很好了,直接用就好了,爲啥還要本身封裝一次?
第一. 經過封裝,我能夠直接把全部的請求參數統一使用字典來傳遞
好比,咱們接口請求須要的數據也就是測試數據每每會保存在excel表裏面,那麼咱們取到後是字符串類型,字符串是沒法做爲請求參數傳遞的,因此我每次都要作數據轉換,再傳遞給接口,爲了節省這個過程,我只須要把這個過程封裝到個人requests裏便可,每次取數據後自動給我處理
第二. 當我想保持某個狀態時,不想每次都初始化一個Session對象,那麼我能夠把它封裝到個人requests裏面,之後直接調用便可
下面來看封裝的代碼
1 """ 2 ------------------------------------ 3 @Time : 2019/7/12 16:14 4 @Auth : linux超 5 @File : sendrequests.py 6 @IDE : PyCharm 7 @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! 8 @QQ : 28174043@qq.com 9 @GROUP: 878565760 10 ------------------------------------ 11 """ 12 import json 13 import requests 14 15 16 class HttpRequests(object): 17 """ 18 eg: request = HttpRequests() 19 response = request(method, url, data) 20 or 21 response = request.send_request(method, url, data) 22 print(response.text) 23 """ 24 def __init__(self): 25 self.session = requests.Session() 26 27 def send_request(self, method, url, params_type='form', data=None, **kwargs): 28 method = method.upper() 29 params_type = params_type.upper() 30 if isinstance(data, str): 31 try: 32 data = json.loads(data) 33 except Exception: 34 data = eval(data) 35 if 'GET' == method: 36 response = self.session.request(method=method, url=url, params=data, **kwargs) 37 elif 'POST' == method: 38 if params_type == 'FORM': # 發送表單數據,使用data參數傳遞 39 response = self.session.request(method=method, url=url, data=data, **kwargs) 40 elif params_type == 'JSON': # 若是接口支持application/json類型,則使用json參數傳遞 41 response = self.session.request(method=method, url=url, json=data, **kwargs) 42 else: # 若是接口須要傳遞其餘類型的數據好比 上傳文件,調用下面的請求方法 43 response = self.session.request(method=method, url=url, **kwargs) 44 # 若是請求方式非 get 和post 會報錯,固然你也能夠繼續添加其餘的請求方法 45 else: 46 raise ValueError('request method "{}" error ! please check'.format(method)) 47 return response 48 49 def __call__(self, method, url, params_type='form', data=None, **kwargs): 50 return self.send_request(method, url, 51 params_type=params_type, 52 data=data, 53 **kwargs) 54 55 def close_session(self): 56 self.session.close() 57 try: 58 del self.session.cookies['JSESSIONID'] 59 except: 60 pass 61 62 63 request = HttpRequests() 64 65 66 if __name__ == '__main__': 67 pass
這個封裝只針對了get請求和post請求,固然你也能夠把put,delete等請求添加在32行代碼後面,實現更多的請求方式
解釋一下30-34行代碼: 這幾行數據是爲了把json和字符串類型的數據轉換爲字典的格式(經過使用字典傳遞接口參數)且能夠處理一些特殊的形式,好比下面這樣的格式
'{"mobilephone": None, "pwd": null}' # 字符串類型的,可是即不是json形式的字符串,也不是字典類型的字符串,由於字典裏面沒有null
封裝測試
如今咱們使用封裝好的方法來測試一下發送登陸和充值接口的請求
""" ------------------------------------ @Time : 2019/7/12 16:16 @Auth : linux超 @File : test_requests.py @IDE : PyCharm @Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error! @QQ : 28174043@qq.com @GROUP: 878565760 ------------------------------------ """ from sendrequests import request import unittest class TestRequests(unittest.TestCase): # 登陸接口地址 login_url = r'http://***/futureloan/mvc/api/member/login' # 登陸接口測試數據 login_test_value = '{"mobilephone": "13691579841", "pwd": 123456}' # 充值接口地址 recharge_url = r'http://***/futureloan/mvc/api/member/recharge' # 充值接口測試數據 recharge_test_value = {"mobilephone": "13691579841", "amount": 10000.00} def test_login_api(self): """登陸接口測試用例""" response = request('get', url=self.login_url, data=self.login_test_value) self.assertTrue(response.json()["code"] == "10001") print("登陸接口測試經過") def test_recharge_api(self): """充值接口測試用例""" response = request('get', url=self.login_url, data=self.login_test_value) try: # 充值接口須要先登陸,才能充值 self.assertTrue(response.json()["code"] == '10001') except AssertionError as e: print('登陸失敗!') raise e else: response = request('post', url=self.recharge_url, data=self.recharge_test_value) self.assertTrue(response.json()["code"] == "10001") print("充值接口測試經過") if __name__ == '__main__': unittest.main()
測試結果
登陸接口測試經過 .. 充值接口測試經過 ---------------------------------------------------------------------- Ran 2 tests in 0.570s OK Process finished with exit code 0
ok,測試代碼執行經過,說明咱們的封裝沒有啥問題, 且能夠正常發送get和post請求,也能夠解決測試數據問題和須要接口依賴的問題
總結
最後咱們再來總結一下本文涉及到的全部的知識點和你須要掌握的
1. requests發送get請求和post請求的方法
get(url, params=None, **kwargs) post(url, data=None, json=None, **kwargs)
2. parmas參數和data參數的區別
因爲get請求無請求體,post請求有請求體
使用params參數時,默認會把參數附加到url後面,因此發送get請求時應使用params參數
使用data參數時,參數會存放到請求體中,因此發送post請求時不能使用params,應使用data,除非接口及支持get又支持post,一樣get請求也不能使用data參數
3. 如何使用Seesion解決接口保持狀態的問題
初始化Session實例,經過這個實例調用request()方法發送請求
4. 最重要的一個封裝方法,並掌握這個封裝該如何使用
主要針對get和post請求的接口
----------------------------真正的勇士, 勇於直面慘淡的Warning、 勇於正視淋漓的Error--------------------------
版權聲明
出處: 博客園Linux超的技術博客--https://www.cnblogs.com/linuxchao/
您的支持是對博主最大的鼓勵,感謝您的認真閱讀
本文版權歸做者全部,歡迎轉載,但未經做者贊成必須保留此段聲明, 且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。
做者: Linux超