总结十五
一.正则模块
正则就是用来筛选字符串中的特定的内容的
正则表达式与re模块的关系
1.正则表达式是一门独立的技术,任何语言都可以使用
2.Python中要想使用正则表达式需要通过re模块
正则在匹配的时候,默认都是贪婪匹配(尽量匹配多的)
可以通过在量词后面加上一个?就可以将贪婪匹配变成非贪婪匹配(惰性匹配)
有无正则校验的区别
# 纯python代码校验 while True: phone_number = input('please input your phone number : ') if len(phone_numbuer) == 11 \ and phone_number.isdigit()\ and (phone_number.startswith('13')) \ or phone_number.startswith('14') \ or phone_number.srartswith('15') \ or phone_number.startswith('18'): print('是合法的手机号码') else: print('不是合法的手机号码') # 正则表达式检验 import re phone_number = input('please input your number : ') if re.match('^(13|14|15|18) [0-9] {9}$',phone_number): print('是合法的手机号码') else: print('不是合法的手机号码')
与re模块没有任何关系,仅仅是测试正则表达式:*http://tool.chinaz.com/regex/*
正则表达式应用场景
1.爬虫
2.数据分析
字符组概念
在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用 [ ] 表示(一个字符组每次只能匹配一个字符)
例子:
1.匹配0-9数字([0123456789]也支持简写[0-9])(如果想匹配,横岗,转移即可)
2.匹配A-Z字母(依据上面的简写规则[A-Z])
3.匹配a-z字母(依据上面的简写规则[a-z])
ps:这种上面的范围必须是从小到大[a-Z]不行,[A-z]可以(但是内部有几个特殊符号),因为内部对应的ASCII码表A是最小的,z是最大的
正则表达式符号介绍
# \w,\s,\d与\W,\S,\D相反的匹配关系(对应的两者结合就是匹配全局)
# \t匹配制表符
# \b匹配结尾的指定单词
优先掌握:
# ^:以什么开头
# $:以什么结尾
ps:^与$连用能够精确匹配固定长度的目标字符,^只能出现在开头(), \$只能出现在结尾
# | :或 ab|abc优先匹配前面的正则表达式ab,匹配上就不再用后面的abc,可以通过调换顺序修改优先级(长的放前面,短的放后面:abc|ab)
# ^出现在 [ ] 中的标示除了^后面的其他都匹配,^直接写在外面,限制字符串的开头
[^a]除了a其他都匹配
[^a-z]除了小写字母a-z其他都匹配
分组:当多个正则符号需要重复多次的时候或者当做一个整体进行其他操作,那么可以用分组的形式,分组在正则的语法中就是()
量词
量词必须跟在正则符号的后面
量词只能够限制紧挨着它的那一个正则符号
# +:想要匹配46461186464321,\d一次只能匹配到一个数字,要想一次将数字全部匹配上需要用到\d+,+表示重复一次或多次,并且正则中默认都是贪婪匹配,越多越好
# *:匹配0次或多次
# ?:匹配0次或一次
ps:
1.对于这个0次也能匹配出来的结果,暂时不用考虑
2.*,+,?的工作区间可以用坐标轴的形式表示出来
# {n}:明确指定个数
注意:量词需要卸载匹配符号的后面,并且只约束紧挨着它的那个正则表达式
分组
# 一次性匹配a1b2c3
用[a-z][0-9]会匹配到三个结果
想法:重复写三次,太麻烦,量词限制离的最近的正则表达式
可以用分组([a-z][0-9])+
# 匹配身份证号
1.^[1-9]\d{13,16}[0-9x]$:不完善的地方在于默认是x的情况下只在18位才可能出现,这个表达式没有做这一层的限制
2.^[1-9]\d{14}(\d{2}[0-9x])?$ 现在不会匹配错误的身份证号了
()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次
3.^([1-9]\d{16}[0-9x]|[1-9]\d{14})$
表示先匹配[1-9]\d{16}[0-9x]如果没有匹配上就匹配[1-9]\d{14}
转义符
在正则表达式中,有很多有特殊意义的是元字符,比如\n和\s等,如果要在正则中匹配正常的“\n”而不是“换行符”就需要对“\”进行转义,变成“\\”。
在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。
所以如果匹配一次“\n”,字符串中要写成“\\\n”,如果匹配一次“\\\n”,字符串中要写成“\\\\\\\\n”。
简便操作,利用r可以让整个字符串都不再转义(了解:r其实就是real的意思,真实不转义)
贪婪匹配与非贪婪匹配
# <.*>:先拿着里面的 . * 去匹配所有的内容,然后再根据>往回退着找,遇到即停止
# <.*?>:先拿着?后面的>去匹配符合条件的最少的内容,然后把匹配到的结果返回
# .*?x : 就是去前面任意长度的字符,知道一个x出现
二.re模块使用
三个必须掌握的方法
1.findall
2.search
3.match
import re # 第一个参数是正则表达式,第二个参数是待匹配的文本内容 ret = re.findall('a', 'eva egon yuan') # 返回所有满足匹配条件的结果,放在列表里 print(ret) ret = re.search('a', 'eva egon yuan') print(ret.group()) # 结果:'a' # 函数会在字符串内查找模式匹配,直到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None,并且需要注意的是如果ret是None,再调用.group()会直接报错。这一易错点可以通过if判断来进行筛选 if ret: print(ret.group()) ret = re.match('a', 'abc').group() # 同search,不过仅在字符串开始处进行匹配 print(ret) # ‘a' # match是从头开始匹配,如果正则规则从头开始可以匹配上,就返回一个对象,需要用group才能显示,如果没匹配上就返回None,调用group()就会报错
其他方法
ret = re.split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 print(ret) # ['', '', 'cd'] ret = re.sub('\d', 'H', 'eva3egon4yuan4', 1) # 将数字替换成'H',参数1表示只替换1个 print(ret) # evaHegon4yuan4 ret = re.subn('\d', 'H', 'eva3egon4yuan4') # 将数字替换成'H',返回元组(替换的结果,替换了多少次) print(ret) obj = re.compile('\d{3}') #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字 ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串 print(ret.group()) #结果 : 123 import re ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> print(next(ret).group()) #查看第一个结果 print(next(ret).group()) #查看第二个结果 print([i.group() for i in ret]) #查看剩余的左右结果
分组优先机制
import re res = re.search('^[1-9]\d{14}(\d{2}[0-9x])?$',110105199812067023) print(res.group()) print(res.group(1)) # 获取正则表达式括号阔起来分组的内容 print(res.group(2)) # search与match均支持获取分组内容的操作 跟正则无关是python机制 # 而针对findall它没有group取值的方法,所以它默认就是分组优先获取的结果 ret = re.findall('www.(baidu|jd).com', 'www.jd.com') print(ret) # ['jd'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可 ret = re.findall('www.(?:baidu|jd).com', 'www.jd.com') # ?:取消分组优先 print(ret) # ['www.jd.com']