视频教程传送门
12、Pytest接口自动化之request模块返回的response对象详解_哔哩哔哩_bilibili
requests是用来发送http请求以及接收http响应的第三方库,主要用于接口自动化测试
pip install requests
PyCharm 快捷键Alt+Enter 自动导包
目录
data和json传参的区别:主要是通过请求头Content-Type来区分
| requests.get(url, params=None, **kwargs) | 发送get请求 url是请求路径,params传递参数 |
| requests.post(url, data=None, json=None, **kwargs) | 发送post请求 url是请求路径,data传递参数,json传递参数 |
| requests.put(url, data=None, **kwargs) | 发送put请求 |
| requests.delete(url, **kwargs) | 发送delete请求 |
| requests.request(method, url, **kwargs) | 发送所有请求,是所有请求的底层方法,会调用:session.request() |
- import requests
-
- class TestRequest:
- #get请求:获取接口统一鉴权码token接口
- def test_get_token(self):
- url = "https://api.xxx.com/token"
- data ={
- #待传参数查看API文档
- "grant_type":"client_credential",
- "appid":"xxx"
- "secret":"xxx"
- }
- res = requests.get(url=url,params=data)
- print(res.json())
-
- if __name__ == '__main__':
- TestRequest().test_get_token()
会用到上述 test_get_token 获取token, 定义一个全局变量access_token存放获取的token
- import requests
-
- class TestRequest:
- #全局变量,类变量,通过类名调用
- access_token= ""
-
- #get请求:获取接口统一鉴权码token接口
- def test_get_token(self):
- ……
- TestRequest.access_token = res.json()['access_token']
-
- #post请求:编辑标签接口
- def test_edit_flag(self):
- url = "https://api.xxx.com/xxx/update?access_token=" + TestRequest.access_token
- data = {
- #参数格式查看API文档
- "tag":{"id":"xxx","name":"xxx"}
- }
- res = requests.post(url=url,json=data)
- print(res.json())
-
- if __name__ == '__main__':
- TestRequest().test_get_token()
- TestRequest().test_edit_flag()
说明:上述 res = requests.post(url=url,json=data) 中 json 改为 data会报错
Content-Type: 是服务器要求传入的报文的内容类型
请求:请求方式、请求路径、请求头、请求正文
postman四种传参方式对应的Content-Type的值如下

| form-data | Content-Type:multipart/form-data | |
| x-www-form-urlencoded | Content-Type:application/x-www-form-urlencoded | |
| raw | text | Content-Type:text/plain |
| javascript | Content-Type:application/javascript | |
| json | Content-Type:application/json | |
| html | Content-Type:text/html | |
| xml | Content-Type:application/xml | |
| binary | Content-Type:application/octet-stream | |
参数说明:
(1)请求的参数是:form-data,代表这是表单传参或者文件上传。type=file
Content-Type:multipart/form-data;
(2)请求的参数是:x-www-form-urlencoded,代表这是表单传参。(k1=v1&k2=v2)
Content-Type:application/x-www-form-urlencoded(data传参)
(3)请求的参数是:raw,代表原始格式传参。
text:Content-Type:text/plain(data传参)
javascript:Content-Type:application/javascript
json:Content-Type:application/json(json传参)
html:Content-Type:text/html
xml:Content-Type:application/xml
(4)请求的参数是:binary,代表原始格式传参。
Content-Type:application/octet-stream
data和json传参以及Content-Type的关系如下:
(1)data传参:报文是dict类型 -> Content-Type:application/x-www-form-urlencoded
报文是str类型 -> Content-Type:text/plain
(2)json传参:报文可以是dict也可以是str -> Content-Type:application/json
data 可以传键值对,即非嵌套的dict,例如{key1:value1,key2:value2},也可以传str格式
json 可以传任何形式的dict(包括嵌套的dict)
json.loads() 把json字符串转化成dict形式
json.dumps() 把dict格式转化成json字符串
例如,上面的edit的例子,也可以改成如下,不会报错
str_data = json.dumps(data)
res = requests.post(url=url,data=str_data)
- #post请求:编辑标签接口
- def test_edit_flag(self):
- url = "https://api.xxx.com/xxx/update?access_token=" + TestRequest.access_token
- data = {
- #参数格式查看API文档
- "tag":{"id":"xxx","name":"xxx"}
- }
- str_data = json.dumps(data)
- res = requests.post(url=url,data=str_data)
- print(res.json())
- #文件上传
- def test_file_upload(self):
- url = "https://api.xxx.com/xxx/uploading?access_token=" + TestRequest.access_token"
- data = {
- "media":open(r"D:\star.png","rb")
- }
- res = requests.request("post",url=url,files=data)
- print(res.json())
get/post/put/delete 都是调用requests.request方法,后者调用 session.request方法
| method | 请求方式 |
| url | 请求路径 |
| params=None | get方式传参 |
| data=None | post/put方式传参 |
| json=None | post方式传参 |
| headers=None | 请求头 |
| cookies=None | 请求cookie |
| files=None | 文件上传 |
| auth=None | 鉴权 |
| timeout=None | 超时 |
| allow_redirects=True | 是否允许重定向 |
| proxies=None | 设置代理 |
| hooks=None | 在请求得到响应后的自定义操作 |
| stream=None | 文件下载 |
| verify=None | ssh认证 |
| cert=None | CA证书 |
| requests.session() | 创建会话对象 |
| res.json() | 获得返回的字典格式的数据 |
| res.text | 获得返回的字符串格式的数据 |
| res.content | 获得返回的bytes字节类型的数据 |
| res.status_code | 返回状态码 |
| res.reason | 返回状态信息 |
| res.cookies | 返回cookie信息 |
| res.encoding | 返回编码格式 |
| res.headers | 返回响应头 |
| res.request.xxx | 返回请求的数据,如:请求头、请求参数 |
需要取到 res.text中,csrf_token的值,使用正则匹配
requests.request() 中传入参数headers
- ……
- #加一个全局变量
- csrf_token = ""
-
- #访问首页接口
- def test_start(self):
- url = "http://xxx"
- res = requests.request(method="get",url=url)
- print(res.json())
- #正则提取,".*?"非贪婪模式、最小匹配
- obj = re.search('name="csrf_token" value="(.*?)"',res.text)
- TestRequest.csrf_token = obj.group(1)
-
- #登录接口
- def test_login(self):
- url = "http://xxx"
- data = {
- "username": "xxx",
- "password": "xxx",
- "csrf_token": TestRequest.csrf_token
- }
- headers = {
- #根据接口文档写
- "Accept": "xxx",
- "X-Requested-With": "XMLHttpRequest"
- }
- res = requests.request(method="post",url=url,data=data,headers=headers)
- print(res.json())
- ……
上述还不好使,打开浏览器控制台,查看Cookies

90%以上的基于web的接口都有cookie鉴权
两种解决方式:使用cookie关联、使用session关联
- #新增全局变量
- php_cookie = ""
-
- #访问首页接口
- def test_start(self):
- ...
- #提取Cookie
- TestRequest.php_cookie = res.cookies
-
- #登录接口
- def test_login(self):
- ...
- res = requests.request(method="post",url=url,data=data,headers=headers,cookies=TestRequest.php_cookie)
- print(res.json())
- #新增全局变量
- sess = requests.session()
-
- #访问首页接口
- def test_start(self):
- ...
- res = TestRequest.sess.request(method="get",url=url)
- ...
-
- #登录接口
- def test_login(self):
- ...
- res = TestRequest.sess.request(method="post",url=url,data=data,headers=headers)
- ...