小编写这篇文章的主要目的,主要是给大家解读关于python接口自动化的一些详细代码实例,具体是什么呢?下面就给各位读者详细的解答下。
前言
我们做接口自动化的过程中,解决端口依赖的相关数据时,一般会采用正则匹配去进行获取有关的信息。
正则匹配,又被称为正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(RegularExpression,在编码中常缩写为regex、regexp或RE)。这是一个特殊的字符序列,它能够帮助你便利的检验一个字符串是否与某种模式匹配。在很多文本编辑器里,正则匹配通常被用来检索、替换那些匹配某个模式的文本。而Python自1.5版本起增加了re模块,它提供Perl风格的正则匹配模式。
一、正则表达式语法
1.1表示单字符
单字符:即表示一个多带带的字符,比如匹配数字用d,匹配非数字用D。
除以下语法,也可以匹配指定的具体字符,可以是1个也可以是多个。
实例如下,这里先说明一下findall(匹配规则,要匹配的字符串)这个方法是查找所有匹配的数据,以列表的形式返回,后面会在re模块进行详解:
import re #.:匹配任意1个字符 re1=r'.' res1=re.findall(re1,'nj8?0nbthnihb') print(res1)#运行结果:['j','8','?','0','b','t','h','i','h','b'] #[]:匹配列举中的其中一个 re2=r"[abc]" res2=re.findall(re2,'1iugfiSHOIFUOFGIDHFGFD2345a6a78b99cc') print(res2)#运行结果:['a','a','b','c','c'] #d:匹配一个数字 re3=r"d" res3=re.findall(re3,"dfghjkl32212dfghjk") print(res3)#运行结果:['3','2','2','1','2'] #D:匹配一个非数字 re4=r"D" res4=re.findall(re4,"d212dk?n$%3;]a") print(res4)#运行结果:['d','d','k','?','n','$','%',';',']','a'] #s:匹配一个空白键或tab键(tab键实际就是两个空白键) re5=r"s" res5=re.findall(re5,"a s d a 9999") print(res5)#运行结果:['','','','',''] #S:匹配非空白键 re6=r"S" res6=re.findall(re6,"a s d a 9999") print(res6)#运行结果:['a','s','d','a','9','9','9','9'] #w:匹配一个单词字符(数字、字母、下划线) re7=r"w" res7=re.findall(re7,"ce12sd #a as_#$") print(res7)#运行结果:['c','e','1','2','s','d','a','a','s','_'] #W:匹配一个非单词字符(不是数字、字母、下划线) re8=r"W" res8=re.findall(re8,"ce12sd #a as_#$") print(res8)#运行结果:[' ','#','','#','$'] #匹配指定字符 re9=r"python" res9=re.findall(re9,"cepy1thon12spython123 python") print(res9)#运行结果:['python','python']
1.2表示数量
如果要匹配某个字符多次,就可以在字符后面加上数量进行表示,具体规则如下:
实例如下:
import re #*:表示前一个字符出现0次以上(包括0次) re21=r"d*"#这里匹配的规则,前一个字符是数字 res21=re.findall(re21,"343aa1112df345g1h6699")#如匹配到a时,属于符合0次,但因为没有值所以会为空 print(res21)#运行结果:['343','','','1112','','','345','','1','','6699',''] #?:表示0次或者一次 re22=r"d?" res22=re.findall(re22,"3 43*a111") print(res22)#运行结果:['3','','4','3','','','1','1','1',''] #{m}:表示匹配一个字符m次 re23=r"1[3456789]d{9}"#手机号:第1位为1,第2位匹配列举的其中1个数字,第3位开始是数字,且匹配9次 res23=re.findall(re23,"sas13566778899fgh256912345678jkghj12788990000aaa113588889999") print(res23)#运行结果:['13566778899','13588889999'] #{m,}:表示匹配一个字符至少m次 re24=r"d{7,}" res24=re.findall(re24,"sas12356fgh1234567jkghj12788990000aaa113588889999") print(res24)#运行结果:['1234567','12788990000','113588889999'] #{m,n}:表示匹配一个字符出现m次到n次 re25=r"d{3,5}" res25=re.findall(re25,"aaaaa123456ghj333yyy77iii88jj909768876") print(res25)#运行结果:['12345','333','90976','8876']
1.2.1匹配分组
实例如下:
import re #同时定义多个规则,只要满足其中一个 re31=r"13566778899|13534563456|14788990000" res31=re.findall(re31,"sas13566778899fgh13534563456jkghj14788990000") print(res31)#运行结果:['13566778899','13534563456','14788990000'] #():匹配分组:在匹配规则的数据中提取括号里的数据 re32=r"aa(d{3})bb"#如何数据符合规则,结果只会取括号中的数据,即d{3} res32=re.findall(re32,"ggghjkaa123bbhhaa672bbjhjjaa 45bb") print(res32)#运行结果:['123','672']
实例如下:
import re #^:匹配字符串的开头 re41=r"^python"#字符串开头为python res41=re.findall(re41,"python999python")#只会匹配这个字符串的开头 res411=re.findall(re41,"1python999python")#因为开头是1,第1位就不符合了 print(res41)#运行结果:['python'] print(res411)#运行结果:[] #$:匹配字符串的结尾 re42=r"python$"#字符串以python结尾 res42=re.findall(re42,"python999python") print(res42)#运行结果:['python'] #b:匹配单词的边界,单词即:字母、数字、下划线 re43=r"bpython"#即匹配python,且python的前一位是不是单词 res43=re.findall(re43,"1python 999 python")#这里第1个python的前1位是单词,因此第1个是不符合的 print(res43)#运行结果:['python']
#B:匹配非单词的边界
re44=r"Bpython"#即匹配python,且python的前一位是单词
res44=re.findall(re44,"1python999python")
print(res44)#运行结果:['python','python']
二、贪婪模式
python里数量词默认是贪婪的,一直试着搭配尽可能多地字段,并非贪婪模式则是试着搭配尽可能少的字段,在表示数量的表达式后加上问号(?)就可以关闭贪婪模式。
如下所示实例,搭配2个以上的大数字,假如满足条件它还会继续获取到不满足才终止,如这里面的34656fya,34656符合2个大数字以上,那么它还会继续获取到6为止,假如关闭贪婪模式,那么在满足2个大数字时就会终止,最后可以获取到34、65。
import re #默认的贪婪模式下 test='aa123aaaa34656fyaa12a123d' res=re.findall(r'd{2,}',test) print(res)#运行结果:['123','34656','12','123'] #关闭贪婪模式 res2=re.findall(r'd{2,}?',test) print(res2)#运行结果:['12','34','65','12','12']
三、re模块
在python中使用正则表达式,就会用到re模块来进行操作,提供的方法一般需要传入两个参数:
参数1:匹配的规则
参数2:要进行匹配的字符串
3.1 re.findall()
查找所有符合规范的字符串,以列表的形式返回。
import re test='aa123aaaa34656fyaa12a123d' res=re.findall(r'd{2,}',test) print(res)#运行结果:['123','34656','12','123'] 3.2re.search() 查找第一个符合规范的字符串,返回的是一个匹配对象,可以通过group()将匹配到的数据直接提取出来。 import re s="123abc123aaa123bbb888ccc" res2=re.search(r'123',s) print(res2)#运行结果:<re.Match object;span=(0,3),match='123'> #通过group将匹配到的数据提取出来,返回类型为str print(res2.group())#运行结果:123
返回的匹配对象中,span为匹配到的数据的下标范围,match则是匹配到的值。
group()参数说明:
不传参数:获取的是匹配到的所有内容
传入数值:可以通过参数来指定,获取第几个分组中的内容(获取第1个分组,传入参数1,获取第2个分组,传入参数2,依次类推。)
import re s="123abc123aaa123bbb888ccc" re4=r"aaa(d{3})bbb(d{3})ccc"#这里分组就是前面说到的匹配语法:() res4=re.search(re4,s) print(res4) #group不传参数:获取的是匹配到的所有内容 #group通过参数指定,获取第几个分组中的内容(获取第1个分组,传入参数1,获取第2个分组,传入参数2,依次类推.. print(res4.group()) print(res4.group(1)) print(res4.group(2))
3.3 re.match()
从字符串的起始位置进行匹配,匹配成功则返回匹配到的对象,如果开头的位置不符合匹配的规则,不会继续往后面去匹配,直接返回None。re.match()与re.search()都是只匹配一个,不一样的是,前者只匹配字符串的开头,后者则是会匹配整个字符串,但只获取第一个符合的数据。
import re s="a123abc123aaa1234bbb888ccc" #match:只匹配字符串的开头,开头不符合就返回None res1=re.match(r"a123",s) res2=re.match(r"a1234",s) print(res1)#运行结果:<re.Match object;span=(0,4),match='a123'> print(res2)#运行结果:None
3.4re.sub()
检索和替换:用于替换字符串中的匹配项
re.sub()参数说明:
参数1:待替换的字符串
参数2:目标字符串
参数3:要进行替换操作的字符串
参数4:可以指定最多替换的次数,非必填(默认替换所有符合规范的字符串)
import re s="a123abc123aaa123bbb888ccc" #<font color="#FF0000">参数1:</font>待替换的字符串 #<font color="#FF0000">参数2:</font>目标字符串 #<font color="#FF0000">参数3:</font>要进行替换操作的字符串 #<font color="#FF0000">参数4:</font>可以指定最多替换的次数,非必填(默认替换所有符合规范的字符串) res5=re.sub(r'123',"666",s,4) print(res5)#运行结果:a666abc666aaa666bbb888ccc
四、用例参数化
在接口自动化测试中,我们的测试数据都是保存在excel中的,有些参数如果写死一个数据,可能换个场景或者换个环境就不能用了,那么切换环境时就需要先把新环境的测试数据准备好,并且能支持去跑我们的脚本,或者把excel的数据修改为适合新环境的测试数据,维护的成本较高。因此就需要把我们的自动化脚本测试数据尽量地参数化,降低维护成本。
我们先看简单版的参数化,以登录为例,登录时用到的账号、密码等信息都可以提取出来放到配置文件,修改数据或更换环境时直接在配置文件中统一修改就可以了。
但如果有多个不同的数据需要参数化呢,每个参数都加个判断去替换数据吗?这样的代码既啰嗦又不好维护,这时re模块就可以用上了,直接看一个实例:
import re from common.myconfig import conf class TestData: """用于临时保存一些要替换的数据""" pass def replace_data(data): r=r"#(.+?)#"#注意这个分组()内的内容 #判断是否有需要替换的数据 while re.search(r,data): res=re.search(r,data)#匹配出第一个要替换的数据 item=res.group()#提取要替换的数据内容 key=res.group(1)#获取要替换内容中的数据项 try: #根据替换内容中的数据项去配置文件中找到对应的内容,进行替换 data=data.replace(item,conf.get_str("test_data",key)) except: #如果在配置文件中找不到就在临时保存的数据中找,然后替换 data=data.replace(item,getattr(TestData,key)) return data
注意这里的正则表达式是有使用?关闭贪婪模式的,因为测试数据中可能会需要参数化2个或以上的数据,如果不关闭贪婪模式,它就只能匹配搭配一个数据,举例如下:
import re data='{"mobile_phone":"#phone#","pwd":"#pwd#","user":#user#}' r1="#(.+)#" res1=re.findall(r1,data) print(res1)#运行结果:['phone#","pwd":"#pwd#","user":#user']注意这里单引号只有一个数据 print(len(res1))#运行结果:1 r2="#(.+?)#" res2=re.findall(r2,data) print(res2)#运行结果:['phone','pwd','user'] print(len(res2))#运行结果:3
另外提到的一个用于临时保存数据的类,这里主要用于保存接口返回的数据,因为有些测试数据是动态变化的,可能要依赖于某个接口,后面的测试用例又需要这些数据,那么我们在接口返回时就可以保存到这个类里作为一个类属性,接着在需要用这个数据的测试用例时,把这个类属性提取出来替换到测试数据中即可。提示:设置属性setattr(对象,属性名,属性值),获取属性值getattr(对象,属性名)。
到此为止,已经给大家介绍到这里了,希望可以为各位读者带来帮助。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/127794.html
摘要:下面跟大家详细分享一下写爬虫抓取静态网站的全过程。而我们上面说的元字符都代表一定的规则和占据一定的字符。 遇到的需求 前段时间需要快速做个静态展示页面,要求是响应式和较美观。由于时间较短,自己动手写的话也有点麻烦,所以就打算上网找现成的。 中途找到了几个页面发现不错,然后就开始思考怎么把页面给下载下来。 由于之前还没有了解过爬虫,自然也就没有想到可以用爬虫来抓取网页内容。所以我采取的办...
摘要:爬虫之简介提供一些简单的式的函数用来处理导航搜索修改分析树等功能。自动将输入文档转换为编码,输出文档转换为编码。已成为和一样出色的解释器,为用户灵活地提供不同的解析策略或强劲的速度。 python爬虫之BeautifulSoup 简介 **Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取...
摘要:今天我来和大家分享一下以及自动化生成工具的开发经验。代码生成工具接着讲讲代码生成工具,对于来讲,有官方的代码生成器,还有其他的同类开源项目比如。现有的代码生成器没有可以开箱即用的,都需要去进行不少的修改。 前言 在开发工作中,经常会遇到新产品、服务上线后,需要将其 API 编写不同语言的 SDK。但不同语言 SDK 中都有很大一部分内容是用来进行 API 的描述,而且这部分代码量是最大...
摘要:今天我来和大家分享一下以及自动化生成工具的开发经验。代码生成工具接着讲讲代码生成工具,对于来讲,有官方的代码生成器,还有其他的同类开源项目比如。现有的代码生成器没有可以开箱即用的,都需要去进行不少的修改。 前言 在开发工作中,经常会遇到新产品、服务上线后,需要将其 API 编写不同语言的 SDK。但不同语言 SDK 中都有很大一部分内容是用来进行 API 的描述,而且这部分代码量是最大...
摘要:今天我来和大家分享一下以及自动化生成工具的开发经验。代码生成工具接着讲讲代码生成工具,对于来讲,有官方的代码生成器,还有其他的同类开源项目比如。现有的代码生成器没有可以开箱即用的,都需要去进行不少的修改。 前言 在开发工作中,经常会遇到新产品、服务上线后,需要将其 API 编写不同语言的 SDK。但不同语言 SDK 中都有很大一部分内容是用来进行 API 的描述,而且这部分代码量是最大...
阅读 873·2023-01-14 11:38
阅读 819·2023-01-14 11:04
阅读 668·2023-01-14 10:48
阅读 1823·2023-01-14 10:34
阅读 873·2023-01-14 10:24
阅读 738·2023-01-14 10:18
阅读 466·2023-01-14 10:09
阅读 500·2023-01-14 10:02