IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Python接口自动化之requests请求封装 -> 正文阅读

[Python知识库]Python接口自动化之requests请求封装

在上一篇Python接口自动化测试系列文章:Python接口自动化之Token详解及应用,介绍token基本概念、运行原理及在自动化中接口如何携带token进行访问。

以下主要介绍如何封装请求。

图片

?还记得我们之前写的get请求、post请求么?

大家应该有体会,每个请求类型都写成单独的函数,代码复用性不强。

接下来将请求类型都封装起来,自动化用例都可以用这个封装的请求类进行请求,我们将常用的get、post请求封装起来。

import?requests
class?RequestHandler:
????def?get(self,?url,?**kwargs):
????????"""封装get方法"""
????????#?获取请求参数
????????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请求错误:?%s"?%?e)
????def?post(self,?url,?**kwargs):
????????"""封装post方法"""
????????#?获取请求参数
????????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请求错误:?%s"?%?e)
????def?run_main(self,?method,?**kwargs):
????????"""
????????判断请求类型
????????:param?method:?请求接口类型
????????:param?kwargs:?选填参数
????????:return:?接口返回内容
????????"""
????????if?method?==?'get':
????????????result?=?self.get(**kwargs)
????????????return?result
????????elif?method?==?'post':
????????????result?=?self.post(**kwargs)
????????????return?result
????????else:
????????????print('请求接口类型错误')
if?__name__?==?'__main__':
????#?以下是测试代码
????#?get请求接口
????url?=?'https://api.apiopen.top/getJoke?page=1&count=2&type=video'
????res?=?RequestHandler().get(url)
????#?post请求接口
????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())

请求结果如下:

{'code':?200,?'message':?'成功!',?'result':?[{'sid':?'31004305',?'text':?'羊:师傅,理个发,稍微修一下就行',?'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':?'机器人女友,除了不能生孩子,其他的啥都会,价格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。以上代码痛点如下:

代码量大:只是封装了get、post请求,加上其他请求类型,代码量较大;

缺少会话管理:请求之间如何保持会话状态。

图片

我们再来回顾下get、post等请求源码,看下是否有啥特点。

get请求源码:

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请求源码:

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)

仔细研究下,发现get、post请求返回的都是request函数。

既然这样,我们再来研究下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)
源码看起来很长,其实只有三行,大部分是代码注释。从源码中可以看出,不管是get还是post亦或其他请求类型,最终都是调用request函数。

既然这样,我们可以不像之前那样,在类内定义get方法、post方法,而是定义一个通用的方法,直接调用request函数即可。看起来有点绕,用代码实现就清晰了。

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):
????????"""关闭session"""
????????self.session.close()
if?__name__?==?'__main__':
????#?以下是测试代码
????#?post请求接口
????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)
响应结果:
{
????"token":?"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InZpdmkiLCJleHAiOjE1ODY4Njk3ODQsImVtYWlsIjoidml2aUBxcS5jb20ifQ.OD4HIv8G0HZ_RCk-GTVAZ9ADRjwqr3o0E32CC_2JMLg",
????"user_id":?1,
????"username":?"vivi"
}
这次请求封装简洁实用,当然小伙伴们也可以根据自己的需求自行封装。
总结:本文主要通过源码分析,总结出一套简洁的请求类封装。

下一篇:unittest单元测试框架,敬请关注。

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

在我的QQ技术交流群里(技术交流和资源共享,广告进来腿给你打断)

可以自助拿走,群号953306497(备注“csdn111”)群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。

?

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:35:50  更:2021-07-31 16:35:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/4 2:57:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码