python学习24天----re模块py正则random模块
Posted piaolaipiaoqu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python学习24天----re模块py正则random模块相关的知识,希望对你有一定的参考价值。
1.转义符()
转义符赋予了一个字符一个特殊的意义,如n变为了 就表示换行符
1)python中的转义
#在字符串前加r表示取消字符串中的所有转移
print("C:a.txt") print(r"C:a.txt") 输出: C:.txt C:a.txt
#在转义符前再加一个就表示取消转义,恢复其原本的意义
print("C:a.txt") print("C:\a.txt") 输出: C:.txt C:a.txt
#在正则表达式中,遇到正则转义,直接在之前加r
总结:在python中‘\\n‘才能匹配到‘\n‘ ,所以只要早测试工具测试成功,那在程序中采用加r的方式即可,即r‘\n‘匹配r‘ ‘
2)正则中的转义
①‘(’ 在正则中匹配一个(
②[()+*?/$.] 在字符组中一些特殊的字符会显出原形(即表示原本的意义),如()+*?/等符号
③所有的w d s 在字符组中都表示它原本的意义
④[-] 减号-只有写在字符组的首位的时候表示普通的减号,写在其他位置表示范围,如[1-9]就表示1-9,如果就是想匹配减号,可以写为[1-9]
2.re模块
使用先导入:import re
1)字符串的匹配
①findall(必会)
#语法:re.findall(‘正则表达式‘,‘待匹配的字符串‘)
#参数:正则表达式,待匹配字符串 返回值类型:列表 返回值个数:1 返回值内容:所有匹配上的项;若没有匹配上,就是一个没有值的列表
import re ret = re.findall(‘d‘,"47823dao123") print(ret) 输出: [‘4‘, ‘7‘, ‘8‘, ‘2‘, ‘3‘, ‘1‘, ‘2‘, ‘3‘]
②search(必会)
#语法:re.search(‘正则表达式‘,‘待匹配的字符串‘)
#参数:正则表达式,待匹配字符串 ;返回值类型:正则匹配结果的对象 ;返回值个数:1; 返回值内容列表: 如果匹配上了就返回对象,如果没有匹配上就返回None
import re ret2 = re.search(‘d‘,"47823dao123") ret3 = re.search(‘d‘,"jaosfjo") print(ret2) print(ret3) 输出: <_sre.SRE_Match object; span=(0, 1), match=‘4‘> None
#返回的对象通过group来匹配到的第一个结果,其他结果无法获取
import re ret2 = re.search(‘d‘,"47823dao123") ret3 = re.search(‘d+‘,"47823dao123") print(ret2.group()) print(ret3.group()) 输出: 4 47823
③match
表示从头开始匹配,不管正则表达式写成什么样,都默认在最前面加一个^,然后再做和search同样的工作
import re ret2 = re.match(‘d+‘,"47823dao123") ret3 = re.match(‘d+‘,"$%47823dao123") print(ret2) print(ret3) #输入None print(ret2.group()) print(ret3.group()) #报错::AttributeError: ‘NoneType‘ object has no attribute ‘group‘ 输出: <_sre.SRE_Match object; span=(0, 5), match=‘47823‘> None 47823 报错: AttributeError: ‘NoneType‘ object has no attribute ‘group‘
#要想search实现和match一样的效果,可以再search的正则表达式最前放加一个^
import re ret2 = re.search(‘^d+‘,"47823dao123") ret3 = re.search(‘^d+‘,"^$%47823dao123") print(ret2) print(ret3) #输入None print(ret2.group()) print(ret3.group()) 输出: <_sre.SRE_Match object; span=(0, 5), match=‘47823‘> None 47823 报错:AttributeError: ‘NoneType‘ object has no attribute ‘group‘
#一般在用search匹配时,可以先用if语句判断一下是否匹配到结果,如果匹配到了,再用group输入匹配到的结果(可避开报错)
import re ret2 = re.search(‘^d+‘,"47823dao123") ret3 = re.search(‘^d+‘,"^$%47823dao123") if ret2:print(ret2.group()) if ret3:print(ret3.group()) 输出: 47823
2)字符串的替换
回顾:replace对字符串的替换
print("HelloWorld".replace("o","e")) 输出: HelleWerld
#replace知道替换次数
print("HelloWorld".replace("o","e",1)) 输出: HelleWorld
①sub(***)
#语法:re.search(‘正则表达式‘,‘将匹配到的字符串替换成什么‘,‘待匹配字符产‘)
import re ret = re.sub(‘d‘,‘W‘,‘Hello8orld‘) ret2 = re.sub(‘d+‘,‘x‘,‘123*123‘) print(ret) print(ret2) 输出: HelloWorld x*x
注:python不能直接操作硬盘中的数据,只能先将硬盘中的数据读到内存中,再操纵内存
#sub指定替换的次数
import re ret = re.sub(‘d+‘,‘x‘,‘123*123*123‘,1) print(ret) 输出: x*123*123
②sub2(***)
#语法:re.search(‘正则表达式‘,‘将匹配到的字符串替换成什么‘,‘待匹配字符产‘)
特点:和sub的区别在于他会将匹配到的次数计算出来,将替换后的字符串与匹配到的次数以元组的形式返回
import re ret = re.subn("d+","X","123dad*sas789jdai456") ret2 = re.subn("d","X","123dad*sas789jdai456") print(ret) print(ret2) 输出: (‘Xdad*sasXjdaiX‘, 3) (‘XXXdad*sasXXXjdaiXXX‘, 9)
3)字符串的切割
回顾:字符串的split方法切割
print("阿狸_泽拉斯_塞拉斯_拉克丝".split("_")) 输出: [‘阿狸‘, ‘泽拉斯‘, ‘塞拉斯‘, ‘拉克丝‘]
①split(***)
#语法:re.split(‘正则表达式‘,‘字符串‘)
#将字符串以正则匹配到的字符串为分割符进行分割,然后将分割后的字符串以元组的形式返回
import re ret = re.split("d+","阿狸123泽拉斯456塞拉斯789拉克丝") print(ret) 输出: [‘阿狸‘, ‘泽拉斯‘, ‘塞拉斯‘, ‘拉克丝‘]
4)进阶方法(爬虫/自动化开发必会)
①compile(*****)---------时间效率
#写的则正则表达式首先要变成python解释器能理解的代码,然后再通过这些代码查找你要匹配的内容,但是如果是一个特别长的正则表达式,并且经常使用同一个方法,那么每次使用时都会编译一遍,导致程序效率降低,所以可以利用compile方法将正则表达式先进行编译
#匹配复数 import re ret = re.compile(‘-0.d+|-[1-9]d+(.d+)?‘) res1 = ret.search("sajod-20ada") res2 = ret.search("-30jdiaojd") res3 = ret.search("jdiaojd-40") print(res1.group()) print(res2.group()) print(res3.group()) 输出: -20 -30 -40
注:如果正则表达式只用一次不会节省时间,只有在多次使用某一个相同的正则表达式的时候,这个compile才会提高程序的效率
②finditer(*****)-----空间效率
#如果一次匹配出来的是海量的时候,不要用findall直接获取匹配到的内容,应该用finditer,通过finditer返回的数据是一个可迭代对象(可一个一个取值),便利迭代器拿到的是一个对象,再通过group取到每一个的值
import re res = re.finditer("d","a21asd5ad5959da2789da") for r in res: print(r.group()) 输出: 2 1 。 7
注:所以的空间效率的提升,都代表着时间的提速
总结:在re模块中,findall方法和split方法都返回一个列表;并且findall和split遇到分组会出现问题,如下:
3.正则表达式和python的re模块
1)findall会优先显示分组中的内容,要想取消分组优先,可以在分组的第一个位置前加一个?: 即(?:正则表达式)
import re ret = re.findall(‘-0.d+|-[1-9]d*(.d+)?‘,‘-1asdada-200‘) print(ret) #正常情况下应该打印处-1和-200,但是输出了[‘‘, ‘‘] res = re.findall("www.baidu.com|www.qq.com","www.qq.com") print(res) #输出[‘www.qq.com‘] rep = re.findall("www.(baidu|qq).com","www.qq.com") #正则表达式表达的意思同上,但是匹配到的内容不是想要的内容 print(rep) #输出:[‘qq‘],,即只匹配到了分组中的内容 输出: [‘‘, ‘‘] [‘www.qq.com‘] [‘qq‘]
#在分组内的第一个位置写【?:】表示取消这个组的分组优先
import re ret = re.findall(‘-0.d+|-[1-9]d*(?:.d+)?‘,‘-1asdada-200‘) print(ret) rep = re.findall("www.(?:baidu|qq).com","www.qq.com") print(rep) 输出: [‘-1‘, ‘-200‘] [‘www.qq.com‘]
2)split方法在遇到分组的时候,会保留分组内,被切掉的内容
import re ret = re.split("(d+)","阿狸123泽拉斯456塞拉斯789拉克丝") print(ret) 输出: [‘阿狸‘, ‘123‘, ‘泽拉斯‘, ‘456‘, ‘塞拉斯‘, ‘789‘, ‘拉克丝‘]
3)search和分组:如果search方法中有分组,通过group(n)就能够获取到group中匹配的内容
import re ret = re.search(‘d+(.d+)(.d+)(.d+)?‘,‘1.2.3.4-2*(60+(-40.35/5)-(-4*3))‘) print(ret.group()) print(ret.group(1)) print(ret.group(2)) print(ret.group(3)) 输出: 1.2.3.4 .2 .3 .4
注:在所有的re模块方法中,只有findall和split方法在遇到分组是会有问题,其他方法都正常
4.分组练习
1)从表达式1-2*(60+(-40.35/5)-(-4*3))获取到所有整数
①直接通过d匹配,不能实现
import re print(re.findall(‘d+‘,"1-2*(60+(-40.35/5)-(-4*3))")) 输出: [‘1‘, ‘2‘, ‘60‘, ‘40‘, ‘35‘, ‘5‘, ‘4‘, ‘3‘]
②匹配出每一个数字(整数和小数都显示),不管正负
import re ret = re.findall(‘d+(?:.d+)?‘,"1-2*(60+(-40.35/5)-(-4*3))") print(ret) 输出: [‘1‘, ‘2‘, ‘60‘, ‘40.35‘, ‘5‘, ‘4‘, ‘3‘]
③利用分组优先显示的特点,先取到分组内部的值(即整数),然后再把匹配到的空字符去掉
import re ret = re.findall(‘d+(?:.d+)|(d+)‘,"1-2*(60+(-40.35/5)-(-4*3))") print(ret) ret.remove(‘‘) print(ret) 输出: [‘1‘, ‘2‘, ‘60‘, ‘‘, ‘5‘, ‘4‘, ‘3‘] [‘1‘, ‘2‘, ‘60‘, ‘5‘, ‘4‘, ‘3‘]
注:当不想要的字符串和想要的字符串发生了冲突,可以把不想要的字符串先匹配出来,然后让其不显示
2)标签匹配,对于如下标签
<a>wahaha</a>
①取出<a>
import re ret = re.findall(‘<w+>‘,r"<a>wahaha</a>") print(ret) 输出: [‘<a>‘]
②只取出a
import re ret = re.findall(‘<(w+)>‘,r"<a>wahaha</a>") #加上分组,使其优先显示 print(ret) 输出: [‘a‘]
③取出里面内容,如wahaha
import re ret = re.findall(‘>(w+)<‘,r"<a>wahaha</a>") #加上分组,使其优先显示 print(ret) 输出: [‘wahaha‘]
④通过search的方式取值
import re ret = re.search(‘<(w+)>(w+)</(w+)>‘,"<a>wahaha</a>") print(ret.group()) print(ret.group(1)) print(ret.group(2)) 输出: <a>wahaha</a> a wahaha
3)分组命名(两个名字相同的分组必须一样)
当需要用到一个部分匹配到的内容和另一个地方必须一样的时候,可以用到分组命名
<?P<name>正则表达式>表示给分组起名字
<?P=name>表示使用这个分组,这里匹配到的内容应和分组中的内容完全相同
import re ret = re.search(‘<(?P<name>w+)>w+</(?P=name)>‘,"<h1>hello</h1>") print(ret.group("name")) 输出: h1
#正常情况下也可使用分组命名的方式获取匹配到的值
import re ret = re.search(r‘<(?P<X>w+)>(?P<Z>w+)</(w+)>‘,r‘<a>hello</b>‘) print(ret.group()) print(ret.group(‘X‘)) print(ret.group(‘Z‘)) 输出: <a>hello</b> a hello
4)通过索引使用分组:1表示使用第一组,即匹配到的内容必须和第一个分组中的内容完全相同
#分组命名第二种写法:如果不给组起名字,也可以用序号来找到对应的组,表示要找的内容和前面的组内容一致,获取的匹配结果可以直接用group(序号)拿到对应的值
import re ret = re.search(r"<(w+)>w+</1>","<h1>hello</h1>") print(ret.group(1)) 输出: h1
6.random模块
随机:在某个范围内取到的每一个值的概率都是相同的
#和随机有关的操作,都用到random模块(如抽奖、彩票、发红包、验证码、洗牌)
1)随机小数
#产生0-1之内的随机小数
import random print(random.random()) 输出: 0.9196700983181918
#取到某个特定范围内的小数
import random print(random.uniform(2,5)) #取2-5之间的随机小数 输出: 2.8264542818054768
2)随机整数
#包含范围内的随机整数
import random print(random.randint(10,20)) #获取一个10-20之间的随机数,包含边界值 输出: 18
#左闭右开区间取随机数
import random print(random.randrange(10,20)) #有可能取到10,但取不到20 输出: 17
#在[1,10]不包含10在内的范围内随机取奇数(即间隔两个数取一个)
import random print(random.randrange(1,10,2)) 输出: 5
3)随机抽取
#随机抽取一个值
import random lst = ["阿狸","泽拉斯","拉克丝",("惩戒之箭","韦鲁斯")] print(random.choice(lst)) 输出: 泽拉斯
#随机获取多个值
import random lst = ["阿狸","泽拉斯","拉克丝",("惩戒之箭","韦鲁斯")] print(random.sample(lst,2)) 输出: [‘阿狸‘, (‘惩戒之箭‘, ‘韦鲁斯‘)]
4)打乱顺序(在原列表的基础上打乱顺序 )
import random lst = ["阿狸","泽拉斯","拉克丝",("惩戒之箭","韦鲁斯")] random.shuffle(lst) print(lst) 输出: [‘阿狸‘, (‘惩戒之箭‘, ‘韦鲁斯‘), ‘拉克丝‘, ‘泽拉斯‘]
注:永远不要起和知道的模块名相同的文件名
以上是关于python学习24天----re模块py正则random模块的主要内容,如果未能解决你的问题,请参考以下文章