最近有个需求,就是数据源那边会过来许多api数据,样例如下:

1
2
3
4
5
/api/login/001-1,10.145.205.53:10081,GET,100
/api/login/001-2,10.145.205.53:10081,GET,100
/api/login/001-3,10.145.205.53:10081,GET,100
/api/login/001-4,10.145.205.53:10081,GET,100
/api/login/index,10.145.205.53:10081,POST,100

可以看到过来的数据除了id字段,其余部分是一样的,这样就造成了数据的重复占用资源,理想的情况是将数据合并成下面的情况:

1
2
/api/login/{id},10.145.205.53:10081,GET,100
/api/login/index,10.145.205.53:10081,POST,100

{id} 来替代无意义的段,并且后面要加入合并出来的/api/login/{id}占总数据量的百分比,PM要求的处理速度是10w条/s,目前做的是第一版,后续会更新第二版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import re,math,datetime
from collections import Counter

def main():
file = open("C:\\Users\\lkm86\\Desktop\\data.csv", "r", encoding="utf-8")
# 读取数据
content = file.readlines()

# 存放要计数的api
patternList = []
# 存放包含数字的api
patternBranch = []
# 存放最终结果
patternDict = {}

# 正则匹配是否包含数字
pattern = re.compile('\/[^\\/]*\d[^\\/]*\/')

# 遍历数据列表
for lines in content:
# 取出api字段
line = lines[:lines.index(",")]
# 给api后面加”/“方面后续正则匹配
if line[-1] != "/":
line += "/"
# 正则匹配是否有包含数字的段
if pattern.findall(line):
# 替换包含数字的段为“{id}”
url = pattern.sub('/{id}/', line)
# 将替换后的api表达式再和别的字段合并放入patternList,后续计数使用
patternList.append(url + lines[lines.index(","):].strip())
# 将加了“/”且未做替换的api和其余字段合并并放入patternBranch,后续过滤符合表达式的api使用
patternBranch.append(line + lines[lines.index(","):].strip())
else:
# 将不包含数字的数据直接放入patternDict,并计算与总数据量的占比
patternDict[lines.strip()] = math.ceil(1 / len(content) * 100)
# 将patternList计数,得到字典cnt,key是patternList的原数据,value是原数据出现的次数
cnt = Counter(patternList)
# 遍历字典cnt
for key in cnt.keys():
# 判断表达式出现次数是否小于2
if cnt[key] < 2:
# 获取表达式中的api字段
str = key[:key.index(",")]
# 将表达式中的api的“{id}”替换为是否包含数字的正则表达式
reString = str.replace("{id}", "[^\\/]*\d[^\\/]*")
# 遍历patternBranch
for line in patternBranch:
# 判断patternBranch中数据的api是否符合正则表达式reString
if re.compile(reString).findall(line[:line.index(",")]):
# 将符合正则表达式的放入patternDict,并计算与总数据量的占比
patternDict[line.strip()] = math.ceil(1 / len(content) * 100)
else:
# 将表达式出现次数大于等于2的放入patternDict,并计算与总数据量的占比
patternDict[key] = math.ceil(cnt[key] / len(content) * 100)

# 遍历最终结果
# for key in patternDict.keys():
# print(key)
# print(patternDict[key])

if __name__ == '__main__':
print("开始时间:")
print(datetime.datetime.now())
main()
print("结束时间:")
print(datetime.datetime.now())

我的文件里是11w条数据,测试结果符合需求:

当然,现在第一版只考虑了出现一个{id}的情况,如果出现像下面的这种数据,这个脚本就不能计算出正确的结果了:

1
2
3
4
/api/login/001-1/index/1
/api/login/001-2/index/2
/api/login/001-3/index/3
/api/login/001-4/index/4

如果出现这种两个甚至多个包含数字的段的情况的话,处理过程就要复杂的多了,这个等后续第二版再来想办法实现。