【接口自动化】04-requests模块详解及接口关联

文章目录:


一、前言

我们前面已经介绍过了pytest,有了这个基础之后,本期开始我们就进入接口自动化轻量封装的学习,我们本期会介绍requests模块的封装,以及一些接口关联的知识。

二、讨论

我们目前常用的接口自动化方案有哪些呢?

基于工具的自动化:他一般适用于中小型的一个项目。

比如:postman+nweman+git/svn+jenkins(使用JavaScript实现的)

基于代码的自动化:适用于大中型的项目。

比如:python+requests+pytest+yaml+热加载+allure+logging+Jenkins

基于平台的自动化:适用于特大型项目

前端:vue

后端:Django(python)、springboot(Java)

三、HTTP协议

HTTP协议:咱们使用的是请求---->响应 模式

主动是请求,被动是响应,所以咱们的重点就是请求。

1、请求的四要素

请求方法 :GET、POST、PUT、DELETE等等

请求路径 :URL

请求头

  • content-type:内容格式
    • multipart/form-data:文件上传
    • application/x-www-form-urlencoded:普通表单
    • application/json:JSON参数
  • User-Agent:请求客户端
  • Accept:预期内容
  • X-Request-With:AJAX声明使用异步请求
  • Cookie:存sessionid

请求体

  • 支持不同的格式、不同的内容
  • 对于表单数据有一个特点,他的数据形式是键值对
  • 对于JSON数据他有一个特点,数据形式是JSON字符串

2、响应的四要素

状态码

  • 2xx:成功
  • 3xx:重定向
  • 4xx:客户端错误
    • 401:缺少身份凭据
    • 403:权限不足
    • 404:资源不存在
    • 405:请求方法不允许
  • 5xx:服务端错误

响应头

  • content-type:可以知道响应格式是什么,用于修饰响应体
  • set-cookies:对cookies设置

响应体 :可以支持不同的格式、不同的内容

响应时间:一个接口一般响应时间是在200~400ms之间的


三、Requests库的详细介绍

1、安装Requests库

咱们的Requests是一个第三方库,我们只有安装之后才可以使用的。

bash 复制代码
# 安装
pip install requests
# 看安装信息
pip show requests

我们Requests他在我们Python领域是我们HTTP请求非常之通用的工具,被广泛用于开发、测试、运维、数据分析、爬虫等等领域。

2、requests发送请求的三种方式

2.1 方式1:request+请求方法

使用request+请求方法的例子:

py 复制代码
import requests

#他有四个方法
requests.get("https://www.baidu.com")
requests.post("https://www.baidu.com")
requests.put("https://www.baidu.com")
requests.delete("https://www.baidu.com")

使用这种方式有一个缺点就是:不支持不常用的方法,他就只有上述四个方法

py 复制代码
# 使用这种方法他不支持不常用的方法
# 比如:
requests.move("https://www.baidu.com")

我们怎么解决呢?我们此时就会使用第二种方法

2.2 方式2:requests.request(构造请求)

注意:所谓的构造请求,就是封装请求的四要素。

使用第二种方法,我们可以直接自己构造请求,所以就避免了第一种的局限性:

py 复制代码
import requests

# 使用第二种方法:常用的方法
requests.request("get", "https://www.baidu.com")
# 不常用的方法,他也允许,不会报错
requests.request("move", "https://www.baidu.com")

第二种相较于第一种:维护成本低,代码比较灵活

虽然,第二种方式好,但是我们更希望掌握第三种,因为他会更加的灵活👇

2.3 方式3:requests.session().request(构造请求)

使用session的话,同一个session他们之间不隔离,不同的session之间隔离:

py 复制代码
import requests

session_1 = requests.session()
session_2 = requests.session()

method = "get"
session_1.request(method, "https://www.baidu.com")
session_1.request(method, "https://www.baidu.com")


session_2.request(method, "https://www.baidu.com")
session_2.request(method, "https://www.baidu.com")

想要不隔离就得使用方法3,那么为什么这个方法可以进行隔离呢?此时我们就得配合源码来看:

首先,第一种方法:request+请求方法 他底层实际是调用我们的request方法,只不过他给我们传递了第一个参数,所以第一种方法底层在调用第二种方法

第二种方法:requests.request(构造请求)他底层在实例化我们的session对象,所以他实际上在调用我们的第三种方法

最后我们第三种方法才是真正的最底层最本质的内容:所以我们说掌握第三种,因为第三种是最底层,最本质的,掌握他其他的自然就掌握了

第三种底层源码:

py 复制代码
def request(
    self,              # 对象自己
    method,            # 请求方法(必填参数)
    url,               # 接口地址(必填参数)
    params=None,       # 查询字符串,会成为URL的一部分
    data=None,         # 表单参数
    headers=None,      # 请求头
    cookies=None,      # cookies
    files=None,        # 文件上传
    auth=None,         # 鉴权类
    timeout=None,      # 超时时间
    allow_redirects=True, # 允许重定向
    proxies=None,      # 设置代理
    hooks=None,        # 钩子,响应之后调用
    stream=None,       # 流式传输
    verify=None,       # 验证SSL证书
    cert=None,         # 自定义SSL证书
    json=None,         # JSON参数
):
  • auth=None, # 鉴权类 这里面有它预设的一些鉴权类,我们一般用不到
  • timeout=None, # 超时时间 可以自己设置一个时间,超过制定时间就会报错,但是我们基本不用,因为我们接口的时间是波动的。
  • allow_redirects=True, # 允许重定向 它默认是为真的,所以默认的情况下接口是重定向的,那他就会自己去处理。
  • proxies=None, # 设置代理 用的不多,因为我们不一定都在代码里设置代理,也可以给系统设置代理。
  • hooks=None, # 钩子,所谓的钩子就是满足一定一的条件之后,它会自动的调用,此处我们用的不多,因为他只有响应之后会调用,而有时候我们在响应之前是需要去做一些事情,所以到时候我们会自己去重新封装我们自己的来用。
  • stream=None, # 流式传输,也就是说你上传或下载一个特别大的文件的时候,那就不适合把整个文件都放到内存里面,此时我们就一点一点的放到内存中,然后我再发到接口,然后再一点一点的放到内存出来,再一点一点的发到接口,就不断的放,知道成功。

我们的request方法中有这么多的参数,这些参数都是供我们去构造请求的。

注意: 由于表单参数和JSON都是在请求体中,所以表单data参数和JSON的JSON参数不能共存,也就是不能同时存在


常用的参数:

py 复制代码
method, # 请求方法(必填)
url, # 接口地址
params = None, # 查询字符串
data = None, # 表单参数
headers = None, # 请求头
cookies = None, # cookies
files = None, # 文件上传
json = None, # json参数

总结:

  1. 上述三种方式本质都是通过session发送请求的,只是封装的程度不同。
  2. 前两种方式每次请求都会新建会话,请求相互隔离;第三种基于同一个 Session,可以实现请求共享与接口关联。
  3. 仅执行单次请求可使用第一种;需要多次请求、接口关联的场景,推荐使用第三种。

3、详细介绍requests发送请求的参数

3.1 查询字符串

查询字符串有两种方式:两种方式效果都是一样的

方式1: 直接使用?拼在URL后面

py 复制代码
import requests

session = requests.session()

session.request(
    method = "get",
    url="https://www.baidu.com?name=弹简特",
)

方式2:

py 复制代码
import requests

session = requests.session()

session.request(
    method = "get",
    url="https://www.baidu.com",
    params={
        "name": "弹简特"
    }
)

3.2 表单参数

如何判断,一个参数是表单参数呢?

两种判断方法:

1)他是一个网页中的form表单,比如:

html 复制代码
<form action="http://www.baidu.com" method="POST">
    <p>用户名:<input type="text" name="username" /></p>
    <p>密码:<input type="password" name="password" /></p>
    <input type="submit" value="Submit" />
</form>

2)他的请求头里面有:x-www-form-urlencoded、multipart/form-data(文件就是通过表单上传的)

有上述两种特点的,那么他的参数就是表单参数。

此时我们构造请求的时候,对于表单参数使用如下所示:

py 复制代码
import requests

session = requests.session()

session.request(
    method = "post",
    url="https://www.baidu.com",
    data={ # 表单参数
        "name": "弹简特"
    },
)

3.3 json参数

如何判断,一个参数是json参数呢?

有两种判断依据:

1)在请求头中是:application/json

2)根据请求的内容来判断,比如:

js 复制代码
{
  "username": "test_user01",
  "password": "123456abc",
  "rememberMe": true,
  "captcha": "a1b2",
  "deviceId": "web-pc-2026"
}

有上述两种特点的,那么他的参数就是json参数。

此时我们构造请求的时候,对于json参数使用如下所示:

py 复制代码
import requests

session = requests.session()

session.request( 
    method = "post",
    url="https://www.baidu.com",
    json={ # json参数
        "name": "弹简特"
    },
)

3.4 文件参数

如何判断,一个参数是文件参数呢?

两种判断方法:

1)他的HTML代码是文件表单,如下:

html 复制代码
<!-- 重点1:必须加 enctype="multipart/form-data" -->
<form action="http://你的接口地址/upload" method="POST" enctype="multipart/form-data">
    <!-- 普通文本参数(做一个参考而已,此处可以不用在意这个) -->
    <p>用户名:<input type="text" name="username" /></p>
    <p>描述:<input type="text" name="desc" /></p>

    <!-- 重点2:文件参数的核心标志:<input type="file"> -->
    <!--type="file" 表示文件上传-->
    <p>上传头像:<input type="file" name="avatar" /></p>
    <p>上传附件:<input type="file" name="files" multiple /></p>

    <input type="submit" value="提交上传" />
</form>

2)在请求头中是:multipart/form-data

有上述两种特点的,那么他的参数就是文件参数。

此时我们构造请求的时候,对于文件参数使用如下所示:

py 复制代码
import requests

session = requests.session()

session.request(
    method="post",
    url="https://www.baidu.com",
    files={ # 文件参数
        "avatar": open("文件路径", "rb")
    },
)

4、requests响应对象的介绍

上述我们介绍完如何构造一个请求,那请求发送到服务器之后,服务器会返回一个响应,这个响应我们封装在Response实例对象中:

Response常用的属性和方法:

py 复制代码
import requests

session = requests.session()

resp = session.request(
    method="post",
    url="https://www.baidu.com",
)

# 1. 状态码:服务器返回的HTTP状态码(如200成功、404不存在、500服务器错误)
print('状态码', resp.status_code)

# 2. 状态说明:HTTP状态码对应的文字描述(如"OK"对应200,"Not Found"对应404)
print('状态说明', resp.reason)

# 3. 响应头:服务器返回的响应头信息(包含Content-Type、Set-Cookie等关键信息)
print('响应头', resp.headers)

# 4. 响应Cookies:服务器设置的Cookies(后续请求可携带这些Cookies维持会话)
print('响应Cookies', resp.cookies)

# 5. 响应体(字节):原始二进制响应内容(下载文件、图片等非文本内容时常用,都是字节,你看不懂)
print('响应体(字节)', resp.content)

# 6. 响应体(字符串):自动按编码解码后的文本响应(处理普通文本/HTML时用)
print('响应体(字符串)', resp.text)

# 7. 响应体(JSON):将响应体解析为Python字典/列表(接口返回JSON时用,非JSON会报错)
print('响应体(JSON)', resp.json())  # 可能会报错,所以此处就设置为了方法

# 8. 响应时间:从请求发起到收到响应的耗时(可用于接口性能测试)
print('响应时间', resp.elapsed)

# 9. 字符编码:requests自动识别的响应内容编码(影响resp.text的解码结果)
print('字符编码', resp.encoding)

四、接口自动化-接口关联

其实接口关联的概念我们在之前的接口测试工具中也有介绍过:

接口关联的详细知识

1、是什么是接口关联

接口关联: 就是从第1个接口的响应中获取内容,用来作为第2个接口的请求参数。

所以接口关联一定是涉及两个接口的,如果是一个接口的话,就不叫接口关联了。

实现思路:

第一步:在第一个接口返回的响应中提取出需要的参数,保存到变量中(对于我们怎么去提取,我们后续会介绍)

第二步:将第一步中提取到的值在拿到我们的响应中带到服务器

2、提取响应中的值的方式

2.1 正则提取

正则提取:适用于所有字符串形式的响应 (包括HTML文本、普通文本、JSON字符串等),使用Python自带的 re 模块实现,无需额外安装依赖。但在处理JSON数据时,写法相对复杂,维护成本较高。

2.2 JSONPATH提取

JSONPath 提取:专门适用于结构化的JSON数据 (需先将响应解析为Python字典/列表),需要安装第三方库(如 jsonpath-ng),优点是写法简洁、可读性强,是接口测试中提取JSON字段的主流方式。

3、案例演示

我们接下里就微信各种平台的一个例子

该例子的准备阶段参考博客:接口关联

我们的第一个接口:

py 复制代码
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx9335efa56e8cbb64&secret=0750c9411423c510fd0c2a1acdc32aa4

他会返回我们的鉴权码,这个鉴权码就好比是我们的身份证,我们后续其他所有的接口都需要带上这个身份证才可以请求。

第二个接口:获取我们创建过的标签,要求带上第一个接口的鉴权码作为参数

bash 复制代码
https://api.weixin.qq.com/cgi-bin/tags/get?access_token=第一个接口的鉴权码

3.1 正则提取

导入正则模块:import re

响应数据形如:

text 复制代码
{
  "access_token": "104_pJh004zniW3I9Q0AZika1qpJd-eI14vSoeq1aYjXfAN5kNeTow64zOJaVv4gbjbJc1K-sGpkQNP7t9-WVWMwMaHXPNMhqJhUtXend_KWMrOywx2sCB0ua21xRqINWVjAHAFON",
  "expires_in": 7200
}
方式1:使用search

使用正则搜索方式:re.search("正则表达式", 从响应结果中提取)

用法:re.search("正则表达式", 目标字符串),第一个参数是正则,第二个参数是要匹配的字符串(如 resp.text)。

正则提取常用语法:左边界(.*?)右边界,用 () 包裹要提取的内容。

提取结果是 Match 对象,需用 .group(1) 取出括号内的内容;如果没匹配到,结果为 None

示例:

py 复制代码
# 导入正则
import re
# 导入requests
import requests
# 方式1:使用search的方式
# 构造请求
session = requests.session()

# 第一个接口
resp = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx9335efa56e8cbb64&secret=0750c9411423c510fd0c2a1acdc32aa4"
)

"""
响应数据形如:
{
  "access_token": "104_pJh004zniW3I9Q0AZika1qpJd-eI14vSoeq1aYjXfAN5kNeTow64zOJaVv4gbjbJc1K-sGpkQNP7t9-WVWMwMaHXPNMhqJhUtXend_KWMrOywx2sCB0ua21xRqINWVjAHAFON",
  "expires_in": 7200
}
"""
token = re.search(r'"access_token"\s*:\s*"(.*?)",', resp.text).group(1)

print(token) # 结果:104_cb8mW0UIG-fwMfIkZika1qpJd-eI14vSoeq1afdgs4N95RTXMN9erWhxOBfownZxEb0DP2wHU1oXzP8_qzWai2IHDmscXCQDwMxYqijNqVkRNptTheLL8trBiFUCSUjAHATJL


# 第二个接口
result = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/tags/get?access_token="+token
)
print("第二个接口的返回值", result.json())
# 结果:
"""
第二个接口的返回值 {'tags': [{'id': 2, 'name': '星标组', 'count': 0}, 
{'id': 100, 'name': '广东', 'count': 0}, 
{'id': 101, 'name': '广东90981787', 'count': 0}, 
{'id': 177, 'name': '广东a1', 'count': 0}, 
{'id': 178, 'name': '1777625769', 'count': 0}, 
{'id': 180, 'name': '广东1777638519', 'count': 0}, 
{'id': 195, 'name': '广东cur_time', 'count': 0}, 
{'id': 196, 'name': '广东1777878346839', 'count': 0}, 
{'id': 197, 'name': '广东1777878776497', 'count': 0}, 
{'id': 198, 'name': '广东1777879114242', 'count': 0},
{'id': 199, 'name': '广东1777879140672', 'count': 0}]}
"""
方式2:使用findall

用法:re.findall("正则表达式", 目标字符串),会返回一个列表 ,包含所有匹配到的括号内的内容,可以直接用下标(如 [0])取值。

py 复制代码
# 导入正则
import re
# 导入requests
import requests
# 方式2:使用findall的方式
# 构造请求
session = requests.session()

# 第一个接口
resp = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx9335efa56e8cbb64&secret=0750c9411423c510fd0c2a1acdc32aa4"
)

"""
响应数据形如:
{
  "access_token": "104_pJh004zniW3I9Q0AZika1qpJd-eI14vSoeq1aYjXfAN5kNeTow64zOJaVv4gbjbJc1K-sGpkQNP7t9-WVWMwMaHXPNMhqJhUtXend_KWMrOywx2sCB0ua21xRqINWVjAHAFON",
  "expires_in": 7200
}
"""
token = re.findall(r'"access_token"\s*:\s*"(.*?)",', resp.text)[0]

print(token) # 结果:104_gNV8dmG1z5NMG81w9g7MoJxGGNgZ-ruPTosOfF4x8j81WxDwXvDiotcGk8l9-_OqeQr9YYog-v_JHb_SnTMFR4qAZfIhbYi2DGg1CRVumDijaWRXt0vmNpbYGl4SBCfAJAWFG


# 第二个接口
result = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/tags/get?access_token="+token
)
print("第二个接口的返回值", result.json())
# 结果:
"""
第二个接口的返回值 
{'tags': [
{'id': 2, 'name': '星标组', 'count': 0}, 
{'id': 100, 'name': '广东', 'count': 0}, 
{'id': 101, 'name': '广东90981787', 'count': 0}, 
{'id': 177, 'name': '广东a1', 'count': 0}, 
{'id': 178, 'name': '1777625769', 'count': 0}, 
{'id': 180, 'name': '广东1777638519', 'count': 0}, 
{'id': 195, 'name': '广东cur_time', 'count': 0}, 
{'id': 196, 'name': '广东1777878346839', 'count': 0}, 
{'id': 197, 'name': '广东1777878776497', 'count': 0}, 
{'id': 198, 'name': '广东1777879114242', 'count': 0}, 
{'id': 199, 'name': '广东1777879140672', 'count': 0}
]}
"""
search()和findall()的核心区别
方法 结果类型 作用
re.search() Match 对象/None 只找第一个匹配项,找到就停止
re.findall() 列表 所有匹配项,返回所有括号里的内容

3.2 JSONPath提取

基础说明

JSONPath 专门用来提取接口返回的 JSON 结构化数据,Python 没有内置该功能,属于第三方库,必须手动安装、导入后才能使用。


第一步:安装依赖库

目前有两个常用包,区分主流版本和老旧版本:

  1. 主流推荐(工作/测试常用)
bash 复制代码
pip install jsonpath-ng
  1. 老旧版本(不推荐,仅了解即可)
bash 复制代码
pip install jsonpath

第二步:导入模块

根据安装的库,选择对应导入方式:

python 复制代码
# 方式1:使用 jsonpath-ng(主流)
from jsonpath_ng import parse

# 方式2:使用旧版 jsonpath(少用)
import jsonpath

第三步:使用前提(必看)

JSONPath 不能直接操作字符串,使用前必须满足 2 个条件:

  1. 拿到接口响应对象 resp
  2. 调用 resp.json(),把JSON 字符串转换成 Python 字典/列表(JSON 对象)。

对比正则:正则直接操作 resp.text(字符串),无需转换。

准备测试数据(全程共用示例 JSON)

使用微信获取access_token接口作为测试接口,后续所有例子都基于该接口返回数据:

python 复制代码
import requests

# 微信获取token接口地址
url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx9335efa56e8cbb64&secret=0750c9411423c510fd0c2a1acdc32aa4"
resp = requests.get(url)

# 核心步骤:转为 Python 字典(JSON 对象)
json_data = resp.json()
print(json_data)
"""
接口返回结构:
{
  "access_token": "104_pJh004zniW3I9Q0AZika1qpJd-eI14vSoeq1aYjXfAN5kNeTow64zOJaVv4gbjbJc1K-sGpkQNP7t9-WVWMwMaHXPNMhqJhUtXend_KWMrOywx2sCB0ua21xRqINWVjAHAFON",
  "expires_in": 7200
}
"""

补充:JSONPath 提取的时候基础符号说明

符号 作用
$ 代表JSON根节点,所有表达式必须以此开头
. 层级连接符,用于访问下一级字段
[索引] 数组下标,从0开始取值
[*] 通配符,匹配数组内所有元素
.. 递归匹配,跨多层级查找字段

方式1:旧版 jsonpath(简单易懂,入门首选)
1. 基础语法格式
python 复制代码
# 固定写法
jsonpath.jsonpath(待提取的字典数据, JSONPath表达式)
  • 参数1:json_dataresp.json() 解析后的字典
  • 参数2:JSONPath 表达式,$ 代表整个 JSON 根节点
  • 返回值:列表 ,匹配不到数据返回 False

实战示例

需求:提取根节点下的 access_token 字段

  1. 表达式写法:$.access_token
  2. 完整代码

第一个接口:

python 复制代码
import jsonpath
# 导入requests
import requests


# 构造请求
session = requests.session()

# 第一个接口
resp = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx9335efa56e8cbb64&secret=0750c9411423c510fd0c2a1acdc32aa4"
)
"""
响应数据形如:
{
  "access_token": "104_pJh004zniW3I9Q0AZika1qpJd-eI14vSoeq1aYjXfAN5kNeTow64zOJaVv4gbjbJc1K-sGpkQNP7t9-WVWMwMaHXPNMhqJhUtXend_KWMrOywx2sCB0ua21xRqINWVjAHAFON",
  "expires_in": 7200
}
"""
# 使用JSON提取值
token = jsonpath.jsonpath(resp.json(), "$.access_token")
print(token)

第二个接口:

py 复制代码
# 第二个接口:注意使用的是同一个session
result = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/tags/get",
    params={ # 查询字符串的第二种写法
        "access_token": token
    }
)
print("第二个接口:", result.json()) # 打印JSON对象形式
"""
结果:
第二个接口: 
{'tags': 
[{'id': 2, 'name': '星标组', 'count': 0}, 
{'id': 100, 'name': '广东', 'count': 0},
 {'id': 101, 'name': '广东90981787', 'count': 0}, 
 {'id': 177, 'name': '广东a1', 'count': 0}, 
 {'id': 178, 'name': '1777625769', 'count': 0}, 
 {'id': 180, 'name': '广东1777638519', 'count': 0}, 
 {'id': 195, 'name': '广东cur_time', 'count': 0}, 
 {'id': 196, 'name': '广东1777878346839', 'count': 0}, 
 {'id': 197, 'name': '广东1777878776497', 'count': 0}, 
 {'id': 198, 'name': '广东1777879114242', 'count': 0}, 
{'id': 199, 'name': '广东1777879140672', 'count': 0}]}
"""

方式2:主流 jsonpath-ng(企业/自动化测试常用)
1. 分步语法(固定两步)
  1. parse() 解析 JSONPath 表达式
  2. find() 去字典中匹配数据,再遍历取值
2. 实战示例(同上面需求,提取 access_token)

具体的解释,看代码的注释

python 复制代码
import requests

# 构造请求会话
session = requests.session()

# 第一个接口:获取 access_token
resp = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx9335efa56e8cbb64&secret=0750c9411423c510fd0c2a1acdc32aa4"
)
"""
响应数据形如:
{
  "access_token": "104_pJh004zniW3I9Q0AZika1qpJd-eI14vSoeq1aYjXfAN5kNeTow64zOJaVv4gbjbJc1K-sGpkQNP7t9-WVWMwMaHXPNMhqJhUtXend_KWMrOywx2sCB0ua21xRqINWVjAHAFON",
  "expires_in": 7200
}
"""

# 1. 将响应转为Python字典:接口返回是 JSON 字符串,这行把它转成 Python 字典,JSONPath 只能操作字典。
json_data = resp.json()

# 2. 解析JSONPath表达式: parse() 作用:把字符串形式的表达式 $.access_token 编译成程序能识别的规则,存到 expr 里。
expr = parse("$.access_token")

# 3. 执行匹配并提取结果: 用上面编译好的规则,去字典里查找内容,返回一组匹配对象(不是直接取值)。这组匹配对象使用match_res存储
match_res = expr.find(json_data)

# 4. 遍历match_res 找出要提取的值
access_token = ""
for item in match_res:
    # item是匹配对象
    # item.value是匹配对象中的内容
    access_token = item.value

print("提取到的access_token:", access_token)

# 第二个接口:复用同一个session,传入上一步拿到的token
result = session.request(
    method="get",
    url="https://api.weixin.qq.com/cgi-bin/tags/get",
    params={  # 查询字符串第二种写法
        "access_token": access_token
    }
)
print("第二个接口:", result.json())  # 打印JSON对象形式
"""
结果:
第二个接口: 
{'tags': 
[{'id': 2, 'name': '星标组', 'count': 0}, 
{'id': 100, 'name': '广东', 'count': 0},
 {'id': 101, 'name': '广东90981787', 'count': 0}, 
 {'id': 177, 'name': '广东a1', 'count': 0}, 
 {'id': 178, 'name': '1777625769', 'count': 0}, 
 {'id': 180, 'name': '广东1777638519', 'count': 0}, 
 {'id': 195, 'name': '广东cur_time', 'count': 0}, 
 {'id': 196, 'name': '广东1777878346839', 'count': 0}, 
 {'id': 197, 'name': '广东1777878776497', 'count': 0}, 
 {'id': 198, 'name': '广东1777879114242', 'count': 0},
{'id': 199, 'name': '广东1777879140672', 'count': 0}]}
"""

拓展:多层级 / 数组数据提取示例
示例1:提取普通多层字段

模拟嵌套结构JSON:

json 复制代码
{
  "code": 200,
  "data": {
    "access_token": "abc123",
    "expires_in": 7200
  }
}

提取内层 access_token

  • 表达式:$.data.access_token
示例2:提取数组内数据(JSON 数组常用)

模拟带数组结构JSON:

json 复制代码
{
  "data": [
    {"access_token": "token01", "expires_in": 7200},
    {"access_token": "token02", "expires_in": 3600}
  ]
}
  1. 提取第一条数据的 access_token:表达式 $.data[0].access_token
  2. 提取所有数据的 access_token:表达式 $.data[*].access_token[*] 代表数组所有元素)

总结 正则 vs JSONPath

正则提取(re)
  • 依赖:Python自带模块,无需安装
  • 适用:所有字符串(普通文本、HTML、JSON字符串等)
  • 常用方法
    1. re.search(正则, 目标字符串):返回匹配对象,用 .group(下标) 取值,只匹配第一个结果
    2. re.findall(正则, 目标字符串):返回列表,用下标取值,匹配所有结果
  • 通用提取句式:左边界(.*?)右边界
JSONPath 提取
  • 依赖:第三方库 ,必须手动 pip 安装
  • 适用:仅处理解析后的JSON字典/列表,不支持原始字符串
  • 调用形式:传入JSON对象 + JSONPath表达式,统一返回列表,通过下标取值
  • 基础句式:$.层级节点

最后,老铁们,我们本期到此就结束了,我们本期主要就是介绍requests库和接口关联的使用,下一期我们将介绍统一请求封装,如果觉得有用,那么点赞关注,我们下一期继续。

相关推荐
delishcomcn2 小时前
AI赋能的薄膜分切机:从自动化到自优化
运维·人工智能·自动化·薄膜分切机
极客先躯2 小时前
高级java每日一道面试题-2026年02月03日-实战篇[Docker]-如何备份和恢复 Docker Volume?
运维·docker·容器·自动化·备份·持久化·恢复
零陵上将军_xdr2 小时前
Shell函数与自动化:让脚本从“能用“进化到“好用“
运维·自动化
MAHATMA玛哈特科技2 小时前
校平机在自动化产线中如何“无缝衔接“
运维·自动化·校平机·矫平机·校平机厂家
求知若渴,虚心若愚。2 小时前
Jenkins 自动化流水线(CICD)
运维·自动化·gitlab
一头老黄牛@2 小时前
飞书 × OpenClaw 接入指南:不用服务器,用长连接把机器人跑起来
数据结构·人工智能·程序人生·算法·决策树·自动化·推荐算法
V搜xhliang024610 小时前
AI智能体的数据安全与合规实践
人工智能·学习·数据分析·自动化·ai编程
见合八方11 小时前
【滤波器】用于红外微型光谱仪的可调谐MEMS-FP滤光片-综述
自动化·soa·光通信·激光雷达·半导体光放大器
Urbano12 小时前
工装外套全制作流程、工序痛点及自动化设备升级方案
运维·自动化