当前位置: 首页 > news >正文

【接口自动化】-2- request模块及通过变量实现接口关联

一、发送请求的三种方式 

第一种:直接调用简洁请求方法
requests.get ()、requests.post () 等是封装好的快捷方式,底层实际调用第二种 requests.request() 。

常用方法格式:

requests.get(url, params=None, **kwargs)  
requests.post(url, data=None, json=None, **kwargs)  
requests.put(url, data=None, **kwargs)  
requests.delete(url, **kwargs)  

第二种:底层通用方法
requests.request() 是更基础的实现,第一种的简洁方法底层调用它,需手动传 method 指定请求类型,格式:

requests.request(method, url, **kwargs)  

第三种:带会话管理的请求
借助 requests.session() 维持会话,自动处理 cookie 关联,适合登录态延续等场景,格式:

requests.session().request(  self,  method,  # 请求方式(如 'GET' 'POST'  ) url,     # 请求路径  params=None,    # 查询参数  data=None,      # 表单参数  json=None,      # JSON 参数  files=None,     # 文件参数  headers=None,   # 请求头  cookies=None,   # cookies 信息  # 还有 auth、timeout 等更多扩展参数  
)  

关系与区别

调用关系:第一种调第二种,第二种调第三种 。

核心差异:第三种(session 方式)能自动维护 cookie ,前两种是独立请求,无会话关联能力 。

核心请求参数

method:填 GET、POST 等 HTTP 请求方法,告诉服务器要执行啥操作(比如 GET 是获取资源,POST 是提交数据 )。

url:接口的访问地址,服务器靠这个定位要请求的资源在哪 。

数据传递参数

params:查询参数,会拼在 URL 后面(格式像 ?key1=value1&key2=value2 ),常用于 GET 请求传数据,让服务器根据这些参数返回对应结果,比如按关键词搜索接口就可能用它传搜索词 。

data:表单参数,Content-Type 一般是 application/x-www-form-urlencoded ,把数据以键值对形式(类似表单提交)发给服务器,POST 请求传简单键值数据常用它 。

json:传 JSON 格式数据,Content-Type 是 application/json ,现在很多接口喜欢用这格式传复杂结构化数据(比如包含嵌套、数组的数据),后端好解析 。

files:文件参数,Content-Type 为 multipart/form-data ,用来上传文件(像图片、Excel 等),比如接口需要上传用户头像时就用它 。

辅助配置参数

headers:请求头,放一些元信息,比如告诉服务器客户端能接受啥数据格式(Accept )、当前请求用的 token(Authorization )、模拟浏览器请求的 User-Agent 等,让服务器更 “懂” 这个请求 。

cookies:存 cookie 信息,有些接口靠 cookie 识别用户身份、维持会话,比如登录后拿 cookie 继续请求需要登录态的接口 。

其他功能参数

auth:用来做鉴权,比如 Basic Auth 这种简单认证,填用户名、密码相关信息,让服务器验证请求是否有权限 。

timeout:设置请求超时时间(单位一般是秒 ),超过这个时间没收到响应,就抛出超时异常,避免程序因接口卡着一直等 。

allow_redirects:布尔值,控制是否自动处理重定向(比如 301、302 跳转 ),True 就自动跳,False 就停在当前响应 。

proxies:配置代理,比如想通过代理服务器转发请求(隐藏真实 IP、走特定网络环境等 ),就填代理的地址(格式像 {"http": "http://代理IP:端口", "https": "https://代理IP:端口"} )。

hooks:钩子函数,在请求的不同阶段(比如发送前、收到响应后 )执行自定义逻辑,方便做一些额外操作(像记录请求耗时、修改响应数据 )。

stream:布尔值,若为 True ,响应内容会以流的形式处理,适合下载大文件时逐步读取,不用一次性加载到内存,省内存 。

verify:控制是否验证 SSL 证书,True 会严格验证(防止中间人攻击等 ),但遇到自签名证书(比如公司内部接口 )会报错,可设为 False 跳过验证(生产环境慎用,有安全风险 )。

cert:指定客户端证书文件路径,有些安全要求高的接口,需要客户端带证书证明身份,就用它配置 。

关于 session 的特点

用 requests.session() 创建的会话,能自动处理 cookie 关联的接口!比如登录接口返回的 cookie ,后续同会话里的请求会自动带上,不用每次手动传,像浏览器保持登录态一样,比单独用 requests.get/post(这些是单次请求,cookie 不自动延续 )方便多了,做接口测试模拟用户连续操作(登录 → 访问个人中心 → 退出 )很实用 。

二、发送请求的参数细节(文字说明 + 代码块)

1. params 传参(查询字符串参数)
  • 说明:参数拼在 URL 后(? 连接,& 分隔多参数 ),会对内容做 urlencode 编码(转 ASCII 形式 )。
  • 代码示例
def test_login(self):params = {"name1": "baili","name2": "百里"}# 三种请求方式示例(按需选一种实际执行,这里仅演示传参写法 )requests.get(url="http://47.107.116.139/phpwind/",  params=params  )# requests.request("GET", "http://47.107.116.139/phpwind/", params=params)# requests.session().request("GET", "http://47.107.116.139/phpwind/", params=params)

2. data 传参(Form 表单参数)
  • 说明
    • 自动加请求头 Content-Type: application/x-www-form-urlencoded 。
    • 对参数做 urlencode 编码(转 ASCII 形式 )。
  • 代码示例
def test_login(self):datas = {"name1": "baili","name2": "百里"}# 三种请求方式示例(按需选一种实际执行 )requests.get(url="http://47.107.116.139/phpwind/",  data=datas  )# requests.request("GET", "http://47.107.116.139/phpwind/", data=datas)# requests.session().request("GET", "http://47.107.116.139/phpwind/", data=datas)

3. json 传参(JSON 参数)
  • 说明
    • 自动加请求头 Content-Type: application/json 。
    • 对参数做 Unicode 编码 。
  • 代码示例
def test_login(self):datas = {"name1": "baili","name2": "百里"}# 三种请求方式示例(按需选一种实际执行 )requests.get(url="http://47.107.116.139/phpwind/",  json=datas  )# requests.request("GET", "http://47.107.116.139/phpwind/", json=datas)# requests.session().request("GET", "http://47.107.116.139/phpwind/", json=datas)

4. files 传参(文件参数)
  • 说明
    • 自动加请求头 Content-Type: multipart/form-data 。
    • 以二进制形式把文件内容放到请求体,支持两种上传方式:
      • 方式 1:直接打开本地文件 。
      • 方式 2:构造虚拟文件元组(文件名、内容、文件类型 )。
  • 代码示例(单文件上传)
def test_login(self):# 方式 1:传本地实际文件datas = {"uploads": open("E:\\shu.png", "rb")  }# 方式 2:构造虚拟文件datas = {"uploads": ("a.png", "阿萨德噶哈都干", "image/png")  }# 三种请求方式示例(按需选一种实际执行 )requests.get(url="http://47.107.116.139/phpwind/",  files=datas  )# requests.request("GET", "http://47.107.116.139/phpwind/", files=datas)# requests.session().request("GET", "http://47.107.116.139/phpwind/", files=datas)

  • 代码示例(多文件 + 混合传参)
def test_login(self):# 多文件上传datas = {"files": open("E:/shu.png", "rb"),  "uploads": ("a.png", "阿萨德噶哈都干", "image/png")  }# 同时传表单 + 文件参数 data1 = {"name1": "baili","name2": "百里"}data2 = {"files": open("E:/shu.png", "rb"),"uploads": ("a.png", "阿萨德噶哈都干", "image/png")}# 三种请求方式示例(按需选一种实际执行 )requests.get(url="http://47.107.116.139/phpwind/",  data=data1,  files=data2  )# requests.request("GET", "http://47.107.116.139/phpwind/", data=data1, files=data2)# requests.session().request("GET", "http://47.107.116.139/phpwind/", data=data1, files=data2)

三、接口关联 

⭐ 接口关联基础逻辑

“接口关联” 就是 前一个接口的返回值,作为后一个接口的入参 ,让多个接口能按业务流程串联(比如登录接口返回 token,后续订单接口用该 token 鉴权)。要实现它,得先从第一个接口响应里精准提取需要的数据,这就用到正则、JsonPath 这类工具。

⭐ 正则表达式(Regex)—— 处理字符串响应

当接口返回是文本 / HTML / 普通字符串,用正则提取数据。Python 里靠 re 库实现,常用方法:

1. 核心方法
  • re.search(pattern, string)
    • 功能:在字符串里找第一个匹配正则的内容,返回 “匹配对象”(没匹配到返回 None )。
    • 取值:用 .group(1) 提取正则里括号捕获的内容(括号是 “捕获分组”,把想要的数据圈出来 )。
  • re.findall(pattern, string)
    • 功能:提取所有匹配正则的内容,返回 “列表”(没匹配到返回空列表 )。
    • 取值:用下标 [0] 取第一个结果(若只有一个匹配,列表就一个元素 )。

2. 代码示例(结合图中案例)

假设 res.text 是接口返回的文本(比如含 csrf_token 的 HTML 或字符串):

import re# 场景:从响应里提取 csrf_token 值
res_text = '...<input name="csrf_token" value="abc123xyz" />...'  # 模拟接口返回# 1. re.search 用法
search_result = re.search('name="csrf_token" value="(.*?)"', res_text)  
if search_result:token = search_result.group(1)  # 取括号里的内容 → "abc123xyz"# 2. re.findall 用法
findall_result = re.findall('name="csrf_token" value="(.*?)"', res_text)  
if findall_result:token = findall_result[0]  # 取列表第一个元素 → "abc123xyz"

  • 正则语法里,(.*?) 是 “非贪婪匹配”,尽可能短地匹配内容,避免把多余字符包含进来(比如防止截取到无关内容 )。
  • 适用场景:接口返回是 HTML 页面、非 JSON 格式字符串,需要提取特定字段时用。

⭐ JsonPath —— 处理 JSON 响应

当接口返回是 JSON 格式(很常见,比如登录返回的 token、用户信息 ),用 JsonPath 提取更方便、直观。Python 里可通过 jsonpath 库(需提前 pip install jsonpath 安装 )实现。

1. 语法规则(核心)

  • $:根节点(表示整个 JSON 数据,提取时从这开始定位 )。
  • .:取子节点(类似 “点语法”,逐层访问 JSON 的键 )。
  • 列表取值:用 [下标] 取列表里的元素(下标从 0 开始 )。
  • ..:递归取值(深度遍历,找所有符合条件的节点 )。
2. 代码 + 案例

假设接口返回的 JSON 数据如下(先转成 Python 字典 / JSON 结构 ):

json_data = {"access_token": "72_Elind8uyQPa_bGMm3nNfEc_ebvrRhvR8thlO-OBA6DkeykyJNOlgXt4far1to9qIoUWzrvT8ws-EWItFNFinIN1XRFUF1jNW-k6169c-yfPlmBOqdmTFFJaV3DgANSeAEAVIN","expires_in": 7200,"mashang": [{"name": "百里"}, {"name": "北凡"}]
}

3. 常用提取场景
  • 取单个字段

    from jsonpath import jsonpath# 取 access_token → 结果:列表形式,取 [0] 拿到值
    access_token = jsonpath(json_data, '$.access_token')[0]  # 取 expires_in → 结果:[7200] → 取 [0] 得 7200
    expires_in = jsonpath(json_data, '$.expires_in')[0]  
    
  • 取列表里的元素

    # 取 mashang 列表第一个元素 → 结果:[{"name": "百里"}] → 取 [0] 得字典
    first_mashang = jsonpath(json_data, '$.mashang[0]')[0]  # 取第一个元素的 name → 结果:["百里"] → 取 [0] 得 "百里"
    first_name = jsonpath(json_data, '$.mashang[0].name')[0]  
    
  • 递归取值(.. 用法)

    # 找所有 name 字段 → 结果:["百里", "北凡"] → 取 [0] 得 "百里"(或遍历列表拿全部)
    all_names = jsonpath(json_data, '$..name')[0]  
    

4. 方法特点

jsonpath.jsonpath() 提取结果是列表

  • 匹配到数据 → 列表存结果(一个结果就长度为 1,多个结果按顺序存 )。
  • 没匹配到 → 返回 False(注意不是 None,判断时要留意 )。

⭐ 实际接口自动化流程(串联思路)

  1. 发送第一个接口请求(比如登录),拿到响应(字符串 / JSON )。
  2. 用 正则 / JsonPath 提取需要的数据(如 token、用户 ID )。
  3. 把提取的数据,作为第二个接口的入参(放到 params / data / json / headers 里 )。
  4. 发送第二个接口请求,实现 “接口关联”。

举个简化的登录 → 获取用户信息流程:

import requests
import re
from jsonpath import jsonpath# 1. 登录接口(假设返回 JSON,含 token)
login_url = "https://example.com/login"
login_data = {"username": "test", "password": "123"}
login_res = requests.post(login_url, data=login_data)
login_json = login_res.json()  # 转 JSON 字典# 2. 用 JsonPath 提取 token
token = jsonpath(login_json, '$.access_token')[0]# 3. 第二个接口(用 token 访问用户信息)
info_url = "https://example.com/user/info"
headers = {"Authorization": f"Bearer {token}"}  # 把 token 放请求头
info_res = requests.get(info_url, headers=headers)# 4. 从用户信息接口提取数据(假设返回 HTML,用正则)
user_name = re.search('<span class="username">(.*?)</span>', info_res.text).group(1)
print(f"提取的用户名:{user_name}")

四、上手练习!完整的实战演练 

import re
import jsonpath
import requestsclass TestApi:# 通过类变量csrf_token = ""access_token = ""sess = requests.session()  # 必须是同一个session回话,保持会话状态def test_phpwind(self):urls = "http://47.107.116.139/phpwind/"# 使用session发起get请求res = TestApi.sess.request(method="get", url=urls)# 正则提取csrf_tokensearch_value = re.search('name="csrf_token" value="(.*?)"', res.text)TestApi.csrf_token = search_value.group(1)print(TestApi.csrf_token)def test_login(self):urls = "http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun"datas = {"username": "baili","password": "baili123","csrf_token": TestApi.csrf_token,  # 从第1个接口的返回值中提取"backurl": "http://47.107.116.139/phpwind/","invite": ""}headerss = {"Accept": "application/json, text/javascript, /; q=0.01","X-Requested-with": "XMLHttpRequest"}# 使用session发起post请求res = TestApi.sess.request(method="post", url=urls, data=datas, headers=headerss)print(res.json())def test_get_token(self):url = "https://api.weixin.qq.com/cgi-bin/token"params = {"grant_type": "client_credential","appid": "wx74a8627810cfa308","secret": "e40a02f9d79a8097df497e6aaf93ab80"}# 使用session发起get请求res = TestApi.sess.request(method="get", url=url, params=params)# JsonPath提取access_tokenjsonpath_value = jsonpath.jsonpath(res.json(), '$.access_token')TestApi.access_token = jsonpath_value[0]print(jsonpath_value[0])def test_edit_flag(self):url = "https://api.weixin.qq.com/cgi-bin/tags/update"params = {"access_token": TestApi.access_token}data = {"tag": {"id": 134, "name": "广东人"}}# 使用session发起post请求res = TestApi.sess.request(method="post", url=url, params=params, json=data)print(res.json())

1. csrf_token和access_token为什么是类变量?

这两个token作为接口关联的参数,必须作为全局变量,才能让所有的函数都使用。因为在其中一个函数中创建的变量出了该函数的作用域就会失效,要是在别的函数里面用就是创建新的变量了,无法做到接口参数关联。

2. 为什么要sess = requests.session()来作为请求方式?

因为request.session.request()可以自动处理 cookie 关联,保持会话状态。

3. TestApi.csrf_token = search_value.group(1)

因为csrf_token是类变量,若使用必须经过类名.去调用。search_value是正则表达式提取出来的结果,.group(1)返回对象值。

4. res.json()

当接口返回的是 JSON 格式数据(响应头中通常有 Content-Type: application/json)时,res.json() 会自动解析这个 JSON 字符串,返回对应的 Python 数据结构(字典 dict 或列表 list),方便后续用 Python 语法(如 [].)提取数据。

5. TestApi.access_token = jsonpath_value[0]

assess_token是类变量,jsonpath_value的返回值是一个列表,[0]是为了取列表中的值(去中括号)

http://www.dtcms.com/a/321346.html

相关文章:

  • 技术融合赋能文旅元宇宙:虚实共生重构产业新生态
  • 宝龙地产债务化解解决方案一:基于资产代币化与轻资产转型的战略重构
  • 苹果iPhone 17系列将发售,如何解决部分软件适配问题引发讨论
  • RabbitMQ 如何实现高可用
  • RabbitMQ面试精讲 Day 17:消费者调优与并发消费
  • 《在 Spring Boot 中安全使用 Qwen API-KEY:环境变量替代明文配置的最佳实践》
  • 五十五、【Linux系统nginx服务】nginx安装、用户认证、https实现
  • 若以微服务部署踩坑点
  • Kiro :从“规范”到“实现”的全流程 AI 助手
  • PBootcms网站模板伪静态配置教程
  • 【新启航】旋转治具 VS 手动翻转:三维扫描中自动化定位如何将单件扫描成本压缩 75%
  • 深度学习圈常见的 TensorFlow、PyTorch、Transformer、transformers,到底有什么区别?
  • WEEX参与欧洲两场重要Web3线下活动,助力社区协作与技术交流
  • c++注意点(15)----设计模式(桥接模式与适配器模式)
  • 机器学习 SVM支持向量机
  • LintCode第433题-岛屿的个数
  • 【同余最短路】P2371 [国家集训队] 墨墨的等式|省选-
  • C5.2:如何利用BJT的区域进行稳定工作
  • 冠雅新品 | 以“无形之光”守护双眸,以“无声之智”浸润生活
  • 冷冻食材,鲜美生活的新选择
  • 深入理解OpenGL Shader与GLSL:基础知识与优势分析
  • 深度学习·Cascade-CLIP
  • Linux中的内核同步源码相关总结
  • 安科瑞EMS3.0:打造“零碳工厂”的智能能源神经中枢
  • 在 Mac 上安装 IntelliJ IDEA
  • 艾体宝产品 | 从“被看见”到“被信任”:GWI 协助洞察消费者,重构品牌认知
  • day21|学习前端vue3框架和ts语言
  • 二十八天(数据结构:图的补充)
  • 璞致电子 PZ-FH8052 高性能 FMC 子卡:超高速信号链的理想解决方案
  • Agent 开发进阶路线:从基础功能到自主决策