python调用接口测试_Python接口测试实战2 - 使用Python发送请求

本节内容

requests安装

requests使用

JSON类型解析

requests库详解

带安全认证的请求

序言

上节课我们学习了接口测试的理论,抓包工具及使用Postman手工测试各种接口,这节课我们主要讲解使用Python语言来发送接口请求,实现接口测试自动化。

发送请求,我们这里主要使用Python的一个第三方包(需要先安装):requests。

Python3自带的http.client和urllib.request都能发送http请求,不过相对来说使用较麻烦,第三方库requests让发送请求更简单,支持自动编码解码,会话保持,长连等

requests安装

Windows: 打开cmd命令行,输入pip install requests,等待安装完成即可

Linux: (建议使用Python3),终端中输入pip3 install requests,等待安装完成即可

Mac: (建议使用Python3), sudo python3 -m pip install requests,等待安装完成即可

验证是否安装成功:

打开命令行,输入python,在python shell环境下输入import requests没有报错即安装成功

requests的使用

一个最简单的GET请求

发送一个请求分3步:

组装请求: 请求可能包含url,params(url参数),data(请求数据),headers(请求头),cookies等,最少必须有url

发送请求,获取响应:支持get,post等各种方法发送,返回的是一个响应对象

解析响应: 输出响应文本

打开Pycharm,新建一个demo项目,项目下新建一个Python文件,输入以下内容:

# 导入requests包

import requests

# 1. 组装请求

url = "http://httpbin.org/get" # 这里只有url,字符串格式

# 2. 发送请求,获取响应

res = requests.get(url) # res即返回的响应对象

# 3. 解析响应

print(res.text) # 输出响应的文本

带参数的GET请求

import requests

url = "http://www.tuling123.com/openapi/api?key=ec961279f453459b9248f0aeb6600bbe&info=你好" # 参数可以写到url里

res = requests.get(url=url) # 第一个url指get方法的参数,第二个url指上一行我们定义的接口地址

print(res.text)

import requests

url = "http://www.tuling123.com/openapi/api"

params = {"key":"ec961279f453459b9248f0aeb6600bbe","info":"你好"} # 字典格式,单独提出来,方便参数的添加修改等操作

res = requests.get(url=url, params=params)

print(res.text)

传统表单类POST请求(x-www-form-urlencoded)

import requests

url = "http://httpbin.org/post"

data = {"name": "hanzhichao", "age": 18} # Post请求发送的数据,字典格式

res = requests.post(url=url, data=data) # 这里使用post方法,参数和get方法一样

print(res.text)

JSON类型的POST请求(application/json)

import requests

url = "http://httpbin.org/post"

data = '''{

"name": "hanzhichao",

"age": 18

}''' # 多行文本, 字符串格式,也可以单行(注意外层有引号,为字符串) data = '{"name": "hanzhichao", "age": 18}'

res = requests.post(url=url, data=data) # data支持字典或字符串

print(res.text)

data参数支持字典格式也支持字符串格式,如果是字典格式,requests方法会将其按照默认表单urlencoded格式转换为字符串,如果是字符串则不转化

如果data以字符串格式传输需要遵循以下几点:

必须是严格的JSON格式字符串,里面必须用双引号,k-v之间必须有逗号,布尔值必须是小写的true/false等等

不能有中文,直接传字符串不会自动编码

一般来说,建议将data声明为字典格式(方便数据添加修改),然后再用json.dumps()方法把data转换为合法的JSON字符串格式

import requests

import json # 使用到JSON中的方法,需要提前导入

url = "http://httpbin.org/post"

data = {

"name": "hanzhichao",

"age": 18

} # 字典格式,方便添加

headers = {"Content-Type":"application/json"} # 严格来说,我们需要在请求头里声明我们发送的格式

res = requests.post(url=url, data=json.dumps(data), headers=headers) # 将字典格式的data变量转换为合法的JSON字符串传给post的data参数

print(res.text)

或直接将字典格式的data数据赋给post方法的JSON参数(会自动将字典格式转为合法的JSON文本并添加headers)

import requests

url = "http://openapi.tuling123.com/openapi/api/v2"

data = {

"reqType":0,

"perception": {

"inputText": {

"text": "附近的酒店"

},

"inputImage": {

"url": "imageUrl"

},

"selfInfo": {

"location": {

"city": "北京",

"province": "北京",

"street": "信息路"

}

}

},

"userInfo": {

"apiKey": "ec961279f453459b9248f0aeb6600bbe",

"userId": "206379"

}

}

res = requests.post(url=url, json=data) # JSON格式的请求,将数据赋给json参数

print(res.text)

练习:

利用图灵聊天接口(GET) http://www.tuling123.com/openapi/api?key=ec961279f453459b9248f0aeb6600bbe&info=你好,结合Python的input编写一个机器人聊天室

利用图灵查询接口(POST)http://openapi.tuling123.com/openapi/api/v2,封装一个实用的查询方法,查询你附近的美食等等

JSON类型解析

序列化和反序列化

程序中的对象,如Python中的字典、列表、函数、类等,都是存在内存中的,一旦断电就会消失,不方便传递或存储,所以我们需要将内存中的对象转化为文本或者文件格式,来满足传输和持久化(存储)需求

序列化: 内存对象 -> 文本/文件

反序列化: 文本 -> 内存对象

对象在HTTP中的传输过程

HTTP协议是超文本传输协议,是通过文本或二进制进行传输的,所以我们发送的请求要转化成文本进行传输,收到的响应也是文本格式,如果是JSON,一般还需要将文本格式重新转化为对象

JSON对象(Python字典) -> 转为文本请求 -> 发送请求

-> 服务器收到文本请求 -> 将文本请求转化为对象,获取其中的参数,处理业务

-> 返回文本格式的响应 -> 客户端转为对象格式来从响应中取值

JSON对象与Python字典的区别

JSON对象是javascript object即javascript中的对象,是一种通用的格式,格式严格,不支持备注。

JSON文本和JSON对象的区别:

JSON文本是符合JSON格式的文本,实际上是一个字符串

JSON对象是内存中一个对象,拥有属性和方法,可以通过对象获取其中的参数信息

Python中我们一般提到JSON对象指的是字典

Python的字典的格式和JSON格式,稍有不同:

字典中的引号支持单引号和双引号,JSON格式只支持双引号

字典中的True/False首字母大写,JSON格式为true/false

字典中的空值为None, JSON格式为null

JSON格式操作方法

序列化(字典 -> 文本/文件句柄): json.dumps()/json.dump()

反序列化(文本/文件句柄 -> 字典) : json.loads()/json.load()

import json # 需要导入JSON包

data = {'name': '张三', 'password': '123456', "male": True, "money": None} # 字典格式

str_data = json.dumps(data) # 序列化,转化为合法的JSON文本(方便HTTP传输)

print(str_data)

输出:{"name": "\u5f20\u4e09", "password": "123456", "male": true, "money": null}

json.dumps()支持将json文本格式化输出

import requests

import json

res = requests.post("http://www.tuling123.com/openapi/api?key=ec961279f453459b9248f0aeb6600bbe&info=怎么又是你")

print(res.text) # 输出为一行文本

res_dict = res.json() # 将响应转为json对象(字典)等同于`json.loads(res.text)`

print(json.dumps(res_dict, indent=2, sort_keys=True, ensure_ascii=False)) # 重新转为文本

看一下输出结果对比:

{"code":100000,"text":"我才要说怎么又是你"} # res.text,有些接口中文会返回为\u..

{

"code": 100000,

"text": "我才要说怎么又是你" # 树状格式,比较清晰,显示中文

}

indent: 缩进空格数,indent=0输出为一行

sork_keys=True: 将json结果的key按ascii码排序

ensure_ascii=Fasle: 不确保ascii码,如果返回格式为utf-8包含中文,不转化为\u...

反序列化

import json

res_text = {"name": "\u5f20\u4e09", "password": "123456", "male": true, "money": null} # JSON文本格式的响应信息

res_dict = json.loads(res_text) # 转化为字典

print(res_dict['name']) # 方便获取其中的参数值

输出:张三

文件的序列化与反序列化

序列化:字典 -> 文件句柄

import json

res_dict = {'name': '张三', 'password': '123456', "male": True, "money": None} # 字典格式

f = open("demo1.json","w")

json.dump(res_dict, f)

查看同级目录,增加了一个demo1.json文件,内容为:

{"name": "\u5f20\u4e09", "password": "123456", "male": true, "money": null}

序列化: 文件句柄 -> 字典

在项目中(和下面脚本文件同一路径下)新建demo2.json文件,内容如下,保存

{

"name": "张三",

"password": "123456",

"male": true,

"money": null

}

新建Python文件

import json

f = open("demo.JSON","r", encoding="utf-8") # 文件中有中文需要指定编码

f_dict = json.load(f) # 反序列化将文件句柄转化为字典

print(f['name']) # 读取其中参数

f.close()

什么时候使用JSON对象(字典)什么时候使用JSON文本?

一般在组装data参数时,建议使用字典格式,发送请求时用json.dumps(data)转化为文本发送,收到请求后使用json.loads(res.text)转化为字典,方便我们获取其中的参数信息

练习:

解析以下json格式文件,发送请求并打印响应

注: method支持get和post,如果没有method,有data默认发post请求,没有data默认发get请求,type支持:form或json,没有默认发form格式

demo1.json

{

"url": "http://www.tuling123.com/openapi/api",

"method": "get",

"params": {

"key": "ec961279f453459b9248f0aeb6600bbe",

"info": "你好"

}

}

demo2.json

{

"url": "http://openapi.tuling123.com/openapi/api/v2",

"method": "post",

"type": "json",

"data": {

"reqType": 0,

"perception": {

"inputText": {

"text": "附近的酒店"

},

"inputImage": {

"url": "imageUrl"

},

"selfInfo": {

"location": {

"city": "北京",

"province": "北京",

"street": "信息路"

}

}

},

"userInfo": {

"apiKey": "ec961279f453459b9248f0aeb6600bbe",

"userId": "206379"

}

}

}

requests库详解

请求方法

requests.get()

requests.post()

requests.put()

...

requests.session(): 用于保持会话(session)

除了requests.session()外,其他请求方法的参数都差不多,都包含url,params, data, headers, cookies, files, auth, timeout等等

请求参数

url: 字符串格式,参数也可以直接写到url中

params:url参数,字典格式

data: 请求数据,字典或字符串格式

headers: 请求头,字典格式

cookies: 字典格式,可以通过携带cookies绕过登录

files: 字典格式,用于混合表单(form-data)中上传文件

auth: Basic Auth授权,数组格式 auth=(user,password)

timeout: 超时时间(防止请求一直没有响应,最长等待时间),数字格式,单位为秒

响应解析

res.status_code: 响应的HTTP状态码

res.reason: 响应的状态码含义

req.text:响应的文本格式,按req.encoding解码

req.content: 响应的二进制格式

req.encoding: 解码格式,可以通过修改req.encoding='utf-8'来解决一部分中文乱码问题

req.apparent_encoding:真实编码,由chardet库提供的明显编码

req.json(): (注意,有括号),响应的json对象(字典)格式,慎用!如果响应文本不是合法的json文本,或报错

req.headers: 响应头

req.cookies: 响应的cookieJar对象,可以通过req.cookies.get(key)来获取响应cookies中某个key对应的值

...

示例:

import requests

res = requests.get("https://www.baidu.com")

print(res.status_code, res.reason) # 200 OK

print(res.text) # 文本格式,有乱码

print(res.content) # 二进制格式

print(res.encoding) # 查看解码格式 ISO-8859-1

print(res.apparent_encoding) # utf-8

res.encoding='utf-8' # 手动设置解码格式为utf-8

print(res.text) # 乱码问题被解决

print(res.cookies.items()) # cookies中的所有的项 [('BDORZ', '27315')]

print(res.cookies.get("BDORZ")) # 获取cookies中BDORZ所对应的值 27315

带安全认证的请求

需要登录的请求(Cookie/Session认证)

未登录访问接口

使用会话保持

import requests

s = requests.session() # 新建一个会话

s.post(url="https://demo.fastadmin.net/admin/index/login.html",data={"username":"admin","password":"123456"}) # 发送登录请求

res = s.get("https://demo.fastadmin.net/admin/dashboard?ref=addtabs") # 使用同一个会话发送get请求,可以保持登录状态

print(res.text)

如果不使用session()而单独发一个post登录请求一个get请求是否可以呢?你可以自己试一下(requests.get()或post()每次都会建立一个新会话)

抓取cookies

import requests

url = "https://demo.fastadmin.net/admin/dashboard?ref=addtabs"

cookies = {"PHPSESSID":"9bf6b19ddb09938cf73d55a094b36726"}

res = requests.get(url=url, cookies=cookies) # 携带cookies发送请求

print(res.text)

两种方式的对比

使用session方式:每次都要发送两次请求,效率较低

使用携带cookies方式:需要手动抓包,提取组装,cookies中是session有一定有效期,过期之后要重新抓取和更换cookies

如果很多或所有请求都需要登录,可以发一次请求,保持该session为全局变量,其他接口都使用该session发送请求(同样要注意登录过期时间)

练习

抓包并用脚本发一条微博或一篇博客

appid或token方式

appid: 系统为合法用户赋予的访问id,固定的字符串,一般经过加密以确保HTTP传输中的安全

token: 即令牌,固定或需要动态申请(有一定有效期),一般由用户信息及申请时间计算加密而成,用于验证接口访问的权限

token与session的区别

session是存在服务器的,服务端通过验证客户端的请求所携带的session值在服务会话中是否存在,来验证用户是否合法

token: 是按一定算法加密计算出来的,服务端通过解密客户端所携带的token值来验证用户是否合法

**示例: **

访问百度AI开发者平台:http://ai.baidu.com/,注册并登录,成为开发者,选择文字识别

根据文档新建应用,查看自己的App Key和Secret Key

创建应用

获取token

通用文字接口

从网络上找一张带文字的图片,右键,复制图片地址(注意不支持https地址的图片)

带文字的图片

请求结果

import requests

import json

app_key = 'kPoFYw85FXsnojsy5bB9hu6x'

secret_key = 'l7SuGBkDQHkjiTPU3m6NaNddD6SCvDMC'

img_url = '//upload-images.jianshu.io/upload_images/7575721-40c847532432e852.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'

# 获取token

get_token_url = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={}&client_secret={}'.format(app_key,secret_key)

token = requests.get(url=get_token_url).json().get("access_token") # 从获取token接口的响应中取得token值

# 识别图片文字

orc_url = 'https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token={}'.format(token)

data = {"url": img_url}

res = requests.post(url=orc_url, data=data)

print(json.dumps(res.json(), indent=2, ensure_ascii=False)) # 格式化输出

显示结果:

{

"log_id": 4745549456768330559,

"words_result_num": 6,

"words_result": [

{

"words": "我又问:那么何时,你带我回去?"

},

{

"words": "莲师言:你是你,我是我。你若不愿流连凡尘,自会回去。"

},

{

"words": "我问莲师:我从哪里来,要到哪里去?"

},

{

"words": "莲师言:世间种种变相,皆有起源。来与去皆是命中定数,不可参度。"

},

{

"words": "我再问:我是否还会再见到你?"

},

{

"words": "莲师言:你若心中有我,自然会再见。"

}

]

}

练习:

自己注册任意一个开发者平台(微信开发者平台,百度开发者平台,饿了么开发者平台),创建应用,根据相应的授权方式获取token,并使用token正常访问一个接口

开放协议授权

reqeusts支持Basic Auth(基本授权)和Digist Auth(摘要授权)

Oauth1.0 Oauth2.0 参考: requests官方文档

Basic Auth

import requests

import json

# 基本授权可以直接在请求方法中使用`auth = (user,password)`

res = requests.get("https://api.github.com/user", auth=("hanzhichao", "hanzhichao123"))

print(json.dumps(res.json(), indent=2, ensure_ascii=False)) # 格式化输出

数字签名

无论是cookie/session还是appid/token方式,只用来验证请求者身份而不验证参数,因此无法防止请求参数被抓包拦截后篡改(仍携带合法的cookie或token)

数字签名(sign或sig)是用来对原始参数整体进行加密后生成的一个字符串,请求时参数和签名一期发送,服务器收到请求后对参数再次计算签名核对和所携带的签名是否一致。

例如: 原始签名{}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/476317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 551. 学生出勤记录 I

1. 题目 给定一个字符串来代表一个学生的出勤记录,这个记录仅包含以下三个字符: A : Absent,缺勤 L : Late,迟到 P : Present,到场如果一个学生的出勤记录中 不超过一个’A’(缺勤) 并且 不超过两个连续的’L’(迟到…

论文阅读笔记(一)【Journal of Machine Learning Research】Natural Language Processing (Almost) from Scratch(未完)

学习内容 题目: 自然语言从零开始 Natural Language Processing (Almost) from Scratch 2021年7月28日 1-5页 这将是一个长期的过程,因为本文长45页; 每天给自己定为5页的任务量! 由于刚开始接触知识图谱,尚未学习N…

python找出录取率最高的年份_Python分析42年高考数据,告诉你高考为什么这么难?...

不同省份的985和211录取率有着比较明显的差距,12个省份的985录取率低于1.5%,安徽,河南,江苏和贵州更是低于1.2%大数据文摘授权转载自数据森麟作者:徐麟对于已经工作的“上班族”来说,6月7号到9号三天无疑是…

知识图谱入门视频(四)

学习内容 小象学院 b站 问题 本体和实体的区别? 苹果公司是一个科技公司,那么苹果公司就是一个实体,它所对应的科技公司就是本体概念。分布式表示和分布式存储 前者是将语义连续化,后者则是一个存不下; 第四部分 应…

FMS3系列(三):创建基于FMS的流媒体播放程序

本文主要介绍怎么去创建基于FMS的流媒体播放程序,Flash客户端通过网络加载FMS服务器上的视频流文件(.flv,.mp4等),实现视频流的播放。 要实现媒体流文件的播放是非常简单的,只要在FMS服务器上提供好流媒体文件,Flash客户端通过Net…

kakfa怎么看消息是否堆积_纯种哈士奇多少钱一只,怎么看是否是纯种哈士奇

纯种哈士奇多少钱一只,怎么看是否是纯种哈士奇哈士奇之前是一种生存在高寒地带的工作犬,近些年迅速占领了家庭宠物的市场,成为最受欢迎的宠物犬之一,由于它精力过于旺盛而且服从性极地因此也让很多人头痛。但是这并不能让人们减少…

论文阅读笔记(二)【ACL2021】知识抽取NER

学习内容 由于刚刚进入知识图谱领域,对该领域的研究热点不是很了解,所以本文直接翻译ACL2021中关于知识抽取NER中各个论文的摘要和共享;并且适时在最后写出自己的理解;同时自己也会在了解完全部后给出各个论文的研究分类。 1. 题…

SQL Server 2000中的数据转换服务 (DTS)

SQL Server 2000中的数据转换服务 (DTS) 更新日期: 2004年06月15日发布者 Diane LarsenEuan Garden, 投稿人 Microsoft Corporation 2000 年 9 月 摘要: 为了完成数据合并、存档和分析等任务;为了进行应用程序开发;为了进行数据库…

LeetCode 599. 两个列表的最小索引总和(哈希map)

1. 题目 假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。 你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假…

python odoo_odoo python 使用缓存

from tools.com_cache import cache, ctime, timeblock# 使用SQL来取得指定商品在指定仓库的库存数量def get_warehouse_stock_qty(self,warehouse_id):self.ensure_one()# 从缓存中查询,如有cache_data cache.warehouse_stock_qty.get([self.id,warehouse_id])if …

项目经理(project manager)刘小备的一天

背景介绍说明:人物:部门经理:汉小帝刘正系统实施部经理:陶小谦项目经理(project manager):刘小备软件Software工程师:关小羽张小飞赵小云马小超黄小忠任务:为江东通信公司开发套管理平台软件Software江东通信公司接口人:鲁小肃时间:2007年某某月某某天当前状态:项目在编码阶段进…

李宏毅机器学习(一)基本概念介绍

学习内容 这是第二次看机器学习的内容,所以这里主要记录的是让我印象深刻的知识点; 但是有两个问题: deep? 为什么不是越深越好?fat? 为什么要套娃,我们只需要将多个sigmoid并排不就好了吗&am…

灰色关联分析_灰色关联分析模型研究综述

灰色关联分析模型研究小结1 引言灰色关联分析是灰色系统理论中十分活跃的一个分支, 其基本思想是根据序列曲线几何形状来判断不同序列之间的联系是否紧密. 基本思路是通过线性插值的方法将系统因素的离散行为观测值转化为分段连续的折线, 进而根据折线的几何特征构造测度关联程…

LeetCode 622. 设计循环队列

1. 题目 设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。 它也被称为“环形缓冲器”。 循环队列的一个好处是我们可以利用这个队列之前用过的空间。 在一个…

solidworks模板_工程师实用高级操作,Solidworks自定义属性链接到工程图模板

下面,我以一个非常简单的零件为例,为大家介绍如何在工程图中链接这些属性。来达到减少工作量节省工作时间的目的。1.这是1个简单的零件,零件的自定义零件属性都已经填写完成。2.制作该零件的工程图文件,这里我以SolidWorks中默认的…

简单的脚本控制面试题

版面上有一个button,一个div,单击button,div中显示当前日期 答案: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xht…

知识图谱入门知识(二)事件抽取(EE)详细介绍

学习内容 本文主要详细介绍事件抽取EE的概念&#xff1b; 装载自&#xff1a;李景鹏 啥是事件抽取(Event Extraction)&#xff1f; 同时这里关于事件抽取的介绍也可以作为补充&#xff1a; 分层网络用于事件参数抽取 事件抽取 事件提取&#xff08;Event Extraction EE&…

post和get传值

//post传值send.aspx: if (e.CommandName "ChaXun") { LinkButton Lik(LinkButton)e.Item.FindControl("LinkButton1"); Context.Items["username"] Lik.CommandArgument.ToString(); Server.Transfer…

交通流元胞自动机模拟仿真 matlab源码_元胞自动机中的时间反演

1.引言——生命游戏1970年&#xff0c;英国数学家约翰何顿康威提出了生命游戏&#xff08;Life Game&#xff09;。生命游戏本质是一个元胞自动机模型&#xff0c;每个元胞可以看作是一个细胞&#xff0c;细胞的产生、繁衍和死亡拥有3条演化规则。1&#xff0e; 如果一个细胞周…

李宏毅机器学习(二)自注意力机制

学习内容 本文以NLP为基础来介绍自注意力机制&#xff0c;而没有用图像为基础&#xff0c;但是其实两者都是相同的。 在图像中我们可以将图像切块&#xff08;块的划分是自定义的&#xff09;&#xff0c;然后计算块与块之间的关系&#xff1b; 这里介绍了self-attention 的由…