Python接口自動(dòng)化淺析requests請(qǐng)求封裝原理
在上一篇Python接口自動(dòng)化測(cè)試系列文章:Python接口自動(dòng)化淺析Token應(yīng)用原理,介紹token基本概念、運(yùn)行原理及在自動(dòng)化中接口如何攜帶token進(jìn)行訪問。
以下主要介紹如何封裝請(qǐng)求
還記得我們之前寫的get請(qǐng)求、post請(qǐng)求么?
大家應(yīng)該有體會(huì),每個(gè)請(qǐng)求類型都寫成單獨(dú)的函數(shù),代碼復(fù)用性不強(qiáng)。
接下來將請(qǐng)求類型都封裝起來,自動(dòng)化用例都可以用這個(gè)封裝的請(qǐng)求類進(jìn)行請(qǐng)求
將常用的get、post請(qǐng)求封裝起來
import requests class RequestHandler: def get(self, url, **kwargs): """封裝get方法""" # 獲取請(qǐng)求參數(shù) params = kwargs.get("params") headers = kwargs.get("headers") try: result = requests.get(url, params=params, headers=headers) return result except Exception as e: print("get請(qǐng)求錯(cuò)誤: %s" % e) def post(self, url, **kwargs): """封裝post方法""" # 獲取請(qǐng)求參數(shù) params = kwargs.get("params") data = kwargs.get("data") json = kwargs.get("json") try: result = requests.post(url, params=params, data=data, json=json) return result except Exception as e: print("post請(qǐng)求錯(cuò)誤: %s" % e) def run_main(self, method, **kwargs): """ 判斷請(qǐng)求類型 :param method: 請(qǐng)求接口類型 :param kwargs: 選填參數(shù) :return: 接口返回內(nèi)容 """ if method == 'get': result = self.get(**kwargs) return result elif method == 'post': result = self.post(**kwargs) return result else: print('請(qǐng)求接口類型錯(cuò)誤') if __name__ == '__main__': # 以下是測(cè)試代碼 # get請(qǐng)求接口 url = 'https://api.apiopen.top/getJoke?page=1&count=2&type=video' res = RequestHandler().get(url) # post請(qǐng)求接口 url2 = 'http://127.0.0.1:8000/user/login/' payload = { "username": "vivi", "password": "123456" } res2 = RequestHandler().post(url2,json=payload) print(res.json()) print(res2.json())
請(qǐng)求結(jié)果如下:
'message': '成功!', 'result': [{'sid': '31004305', 'text': '羊:師傅,理個(gè)發(fā),稍微修一下就行', 'type': 'video', 'thumbnail': 'http://wimg.spriteapp.cn/picture/2020/0410/5e8fbf227c7f3_wpd.jpg', 'video': 'http://uvideo.spriteapp.cn/video/2020/0410/5e8fbf227c7f3_wpd.mp4', 'images': None, 'up': '95', 'down': '1', 'forward': '0', 'comment': '25', 'uid': '23189193', 'name': '青川小舟', 'header': 'http://wimg.spriteapp.cn/profile/large/2019/12/24/5e01934bb01b5_mini.jpg', 'top_comments_content':None, 'top_comments_voiceuri': None, 'top_comments_uid': None, 'top_comments_name': None, 'top_comments_header': None, 'passtime': '2020-04-12 01:43:02'}, {'sid': '30559863', 'text': '機(jī)器人女友,除了不能生孩子,其他的啥都會(huì),價(jià)格239000元', 'type': 'video', 'thumbnail': 'http://wimg.spriteapp.cn/picture/2020/0306/5e61a41172a1b_wpd.jpg', 'video': 'http://uvideo.spriteapp.cn/video/2020/0306/5e61a41172a1b_wpd.mp4', 'images': None, 'up': '80', 'down': '6', 'forward': '3', 'comment': '20', 'uid': '23131273', 'name': '水到渠成', 'header': 'http://wimg.spriteapp.cn/profile/large/2019/07/04/5d1d90349cd1a_mini.jpg', 'top_comments_content': '為游戲做的秀', 'top_comments_voiceuri': '', 'top_comments_uid': '10250040', 'top_comments_name': '不得姐用戶', 'top_comments_header': 'http://wimg.spriteapp.cn/profile', 'passtime': '2020-04-11 20:43:49'}]} {'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InZpdmkiLCJleHAiOjE1ODY4NTc0MzcsImVtYWlsIjoidml2aUBxcS5jb20ifQ.k6y0dAfNU2o9Hd9LFfxEk1HKgczlQfUaKE-imPfTsm4', 'user_id': 1, 'username': 'vivi'}
這樣就完美了嗎,no,no,no。
以上代碼痛點(diǎn)如下:
代碼量大:只是封裝了get、post請(qǐng)求,加上其他請(qǐng)求類型,代碼量較大;
缺少會(huì)話管理:請(qǐng)求之間如何保持會(huì)話狀態(tài)。
我們?cè)賮砘仡櫹耮et、post等請(qǐng)求源碼,看下是否有啥特點(diǎn)。
get請(qǐng)求源碼:
def get(url, params=None, **kwargs): r"""Sends a GET request. :param url: URL for the new :class:`Request` object. :param params: (optional) Dictionary, list of tuples or bytes to send in the query string for the :class:`Request`. :param \*\*kwargs: Optional arguments that ``request`` takes. :return: :class:`Response <Response>` object :rtype: requests.Response """ kwargs.setdefault('allow_redirects', True) return request('get', url, params=params, **kwargs)
post請(qǐng)求源碼:
def post(url, data=None, json=None, **kwargs): r"""Sends a POST request. :param url: URL for the new :class:`Request` object. :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:`Request`. :param json: (optional) json data to send in the body of the :class:`Request`. :param \*\*kwargs: Optional arguments that ``request`` takes. :return: :class:`Response <Response>` object :rtype: requests.Response """ return request('post', url, data=data, json=json, **kwargs)
仔細(xì)研究下,發(fā)現(xiàn)get、post請(qǐng)求返回的都是request函數(shù)。
再來研究下request源碼:
def request(method, url, **kwargs): """Constructs and sends a :class:`Request <Request>`. :param method: method for the new :class:`Request` object. :param url: URL for the new :class:`Request` object. :param params: (optional) Dictionary, list of tuples or bytes to send in the query string for the :class:`Request`. :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:`Request`. :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`. :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`. :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`. :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload. ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')`` or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers to add for the file. :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. :param timeout: (optional) How many seconds to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) <timeouts>` tuple. :type timeout: float or tuple :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``. :type allow_redirects: bool :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to ``True``. :param stream: (optional) if ``False``, the response content will be immediately downloaded. :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair. :return: :class:`Response <Response>` object :rtype: requests.Response Usage:: >>> import requests >>> req = requests.request('GET', 'https://httpbin.org/get') <Response [200]> """ # By using the 'with' statement we are sure the session is closed, thus we # avoid leaving sockets open which can trigger a ResourceWarning in some # cases, and look like a memory leak in others. with sessions.Session() as session: return session.request(method=method, url=url, **kwargs)
源碼看起來很長,其實(shí)只有三行,大部分是代碼注釋。
從源碼中可以看出,不管是get還是post亦或其他請(qǐng)求類型,最終都是調(diào)用request函數(shù)。
既然這樣,我們可以不像之前那樣,在類內(nèi)定義get方法、post方法,而是定義一個(gè)通用的方法
直接調(diào)用request函數(shù)
看起來有點(diǎn)繞,用代碼實(shí)現(xiàn)就清晰了。
import requests class RequestHandler: def __init__(self): """session管理器""" self.session = requests.session() def visit(self, method, url, params=None, data=None, json=None, headers=None, **kwargs): return self.session.request(method,url, params=params, data=data, json=json, headers=headers,**kwargs) def close_session(self): """關(guān)閉session""" self.session.close() if __name__ == '__main__': # 以下是測(cè)試代碼 # post請(qǐng)求接口 url = 'http://127.0.0.1:8000/user/login/' payload = { "username": "vivi", "password": "123456" } req = RequestHandler() login_res = req.visit("post", url, json=payload) print(login_res.text)
響應(yīng)結(jié)果:
{ "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InZpdmkiLCJleHAiOjE1ODY4Njk3ODQsImVtYWlsIjoidml2aUBxcS5jb20ifQ.OD4HIv8G0HZ_RCk-GTVAZ9ADRjwqr3o0E32CC_2JMLg", "user_id": 1, "username": "vivi" }
這次請(qǐng)求封裝簡潔實(shí)用,當(dāng)然小伙伴們也可以根據(jù)自己的需求自行封裝。
以上就是Python接口自動(dòng)化淺析requests請(qǐng)求封裝原理的詳細(xì)內(nèi)容,更多關(guān)于Python接口自動(dòng)化requests請(qǐng)求封裝的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- python?包?requests?實(shí)現(xiàn)請(qǐng)求操作
- Python接口自動(dòng)化之淺析requests模塊get請(qǐng)求
- 詳解python requests中的post請(qǐng)求的參數(shù)問題
- python 實(shí)現(xiàn)Requests發(fā)送帶cookies的請(qǐng)求
- python中requests模擬登錄的三種方式(攜帶cookie/session進(jìn)行請(qǐng)求網(wǎng)站)
- python爬蟲使用requests發(fā)送post請(qǐng)求示例詳解
- Python接口自動(dòng)化之request請(qǐng)求封裝源碼分析
相關(guān)文章
Python獲取Windows或Linux主機(jī)名稱通用函數(shù)分享
這篇文章主要介紹了Python獲取Windows或Linux主機(jī)名稱通用函數(shù)分享,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2014-11-11pycharm安裝opencv-python報(bào)錯(cuò)的解決
本文主要介紹了pycharm安裝opencv-python報(bào)錯(cuò)的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07使用 Python 創(chuàng)建一個(gè)基于規(guī)則的聊天機(jī)器人
這篇文章主要介紹了使用 Python 創(chuàng)建一個(gè)基于規(guī)則的聊天機(jī)器人,使用 Python 創(chuàng)建一個(gè)簡單的基于規(guī)則的聊天機(jī)器人 聊天機(jī)器人本身是一種機(jī)器或軟件,它通過文本或句子模仿人類交互。 簡而言之,可以使用類似于與人類對(duì)話的軟件進(jìn)行聊天。2021-10-10詳解Django將秒轉(zhuǎn)換為xx天xx時(shí)xx分
這篇文章主要介紹了Django將秒轉(zhuǎn)換為xx天xx時(shí)xx分,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09解決pycharm最左側(cè)Tool Buttons顯示不全的問題
今天小編就為大家分享一篇解決pycharm最左側(cè)Tool Buttons顯示不全的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-12-12python實(shí)現(xiàn)網(wǎng)頁錄音效果
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)網(wǎng)頁錄音效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-10-10解決python 讀取excel時(shí) 日期變成數(shù)字并加.0的問題
這篇文章主要介紹了python 讀取excel時(shí), 日期變成數(shù)字并加.0的問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10