apitest_unittest/common/data_extraction/data_extractor.py

151 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding:utf-8 -*-
"""
Time: 2020/6/1/001 15:29
Author: kira
Email:262667641@qq.com
Project:api_project
"""
import json
import re
import sys
sys.path.append("../")
sys.path.append("./common")
from jsonpath_ng import parse
from common.utils.environments import Environments
from common.data_extraction import logger
REPLACE_DICT = {
"null": None,
"True": True,
"false": False
}
class DataExtractor(Environments):
def __init__(self):
super().__init__()
@logger.log_decorator("提取参数出现了意想不到的错误!!")
def substitute_data(self, response, regex=None, keys=None, deps=None, jp_dict=None):
"""
方法接收一个正则表达式 regex 和一个关联参数表 deps用于从接口返回的数据中提取关联参数。
它会从接口返回的数据中使用正则表达式 regex 和正则表达式返回结果的键列表 keys 提取数据,并将其更新到关联参数表中。
然后,它会使用 subs_deps 和 subs_lists 方法提取更多的关联参数。最后,它将更新后的关联参数表设置为 Environments 类的静态变量,并将其返回
Args:
response: 被提取数据对象
regex: 正则表达式: r'"id": (\d+), "name": "(\w+)",'
keys: 接收正则表达式返回结果的key ["a", "b"]
deps: "name=data[0].name;ok=data[0].id;an=data[0].age[3].a"
jp_dict: jsonpath 提取方式入参:{"k": "$.data", "x": "$.data[0].age[3].a"}
Returns:
"""
response = response
if not isinstance(response, (dict, str, list)):
logger.error(f"被提取对象非字典、非字符串、非列表不执行jsonpath提取被提取对象: {response}")
return {}
if regex and keys:
self.substitute_regex(response, regex, keys)
response = response if isinstance(response, (dict, list)) else json.loads(response)
if deps:
self.substitute_route(response, deps)
if jp_dict:
self.substitute_jsonpath(response, jp_dict)
def substitute_regex(self, response, regex, keys):
"""
方法用于使用正则表达式 regex 和正则表达式返回结果的键列表 keys 从接口返回的数据中提取数据,并将其更新到关联参数表中。
Args:
response:
regex: 正则表达式r'"id": (\d+), "name": "(\w+)",'
keys:结果键列表:["a", "b"],
Returns:
"""
response = json.dumps(response) if isinstance(response, (dict, list)) else response
match = re.search(regex, response)
if not match:
return {}
groups = match.groups()
for i, key in enumerate(keys):
try:
self.update_environments(key, groups[i])
except:
self.update_environments(key, None)
def substitute_route(self, response, route_str):
"""
想字典一样取值:name=data[0].name;ok=data[0].id;an=data[0].age
Args:
response:
route_str:
Returns:
"""
deps_list = re.sub(f"[\r\n]+", "", route_str).split(";")
for dep_item in deps_list:
key, value_path = dep_item.split("=")
value_path_parts = re.findall(r'\w+', value_path)
temp = response
for part in value_path_parts:
if isinstance(temp, dict):
temp = temp.get(part)
elif isinstance(temp, list):
if part.isdigit():
index = int(part)
if index < len(temp):
temp = temp[index]
else:
temp = None
break
else:
temp = None
break
else:
temp = None
break
if isinstance(temp, (dict, list)):
continue
else:
break
if temp is not None:
self.update_environments(key, temp)
def substitute_jsonpath(self, response, json_path_dict):
"""
jsonpath 提取参数
Args:
response: 响应结果
json_path_dict: {"k": "$.data", "x": "$.data[0].age[3].a"}
Returns: 字符串或者list
"""
json_path_dict = json_path_dict if isinstance(json_path_dict, dict) else json.loads(json_path_dict)
for key, expression in json_path_dict.items():
try:
parsed_expression = parse(expression)
data = response
# 使用解析器对象进行匹配和提取
match = parsed_expression.find(data)
result = [m.value for m in match]
self.update_environments(key, result[0]) if len(result) == 1 else self.update_environments(key,
result)
except Exception as e:
logger.error(f"jsonpath表达式错误'{expression}': {e}")
if __name__ == '__main__':
# 测试subs函数
res = '{"code": 1,"data": [{"id": 1, "name": "Alice", "age": [20, 21, 22, {"a": "b"}]}]}'
lists = {"k": "$..code", "x": "$.data[0].age[3].a"}
dep_str = "name=data[0].name;ok=data[0].id;an=data[0].age"
regex_str = r'"id": (\d+), "name": "(\w+)",'
regex_key = ["a", "b"]
t = DataExtractor()
t.substitute_data(res, regex=regex_str, keys=regex_key, deps=dep_str, jp_dict=lists)
print("-------->res:", t.get_environments())