目录
模块的定义
模块的类型
re模块
三个查找方法 findall search match
字符串处理扩展:替换 切割
re模块进阶
compile :节省使用正则表达式解决问题的时间
finditer 节省使用正则表达式解决问题的时间/内存
分组在re模块中的使用
分组命名
正则表达式的使用技巧
匹配整数
匹配标签
爬虫实例
模块就是功能的集合, 模块是python提供给我们去操作这个内容的方法,这个要操作的内容本来就存在。
例:时间模块 在python中操作时间,在python中显示时间 计算时间
在python中使用正则表达式,先要导入re模块
findall:匹配所有能匹配上的,每一项都是列表中的一个元素
语法:findall(正则表达式,待匹配的字符串,flag)
实例:
import re
ret=re.findall('\d+','shdu128wer93')
print(ret)
结果:
['128', '93']
search:只匹配从左到右的第一个,得到的不是匹配的结果,而是一个变量,通过变量的group方法获取结果。如果没有匹配到会返回None,使用group会报错。
实例:
import re
ret=re.search('\d+','shdu128wer93')
print(ret)#内存地址,这是一个正则匹配的结果 <_sre.SRE_Match object; span=(4, 7), match='128'>
print(ret.group())#通过ret.group()获取真正的结果 128
如果没有匹配到会返回None,使用group会报错。
推荐写法:
ret=re.search('\d+','shdu128wer93')
if ret:
print(ret.group()) #128
match:从头开始匹配,相当于search中的正则表达式加上'^'
实例:
ret=re.match('\d+','shdu128wer93')
#ret=re.match('^\d+','shdu128wer93')
print(ret) #None
ret=re.match('\d+','128shduwer93')
#print(ret) #<_sre.SRE_Match object; span=(0, 3), match='128'>
split:返回列表,按照正则表达式切割,默认匹配到的内容会被切割
实例:
s='alex83taibai83egon25'
ret=re.split('\d+',s)
print(ret) #['alex', 'taibai', 'egon', '']
sub: (正则表达式,将匹配的内容替换,待匹配的字符串,替换次数)
实例:将字符串中的数字替换成H,要求替换一次
ret=re.sub('\d+','H','alex83taibai83egon25',1)
print(ret) #alexHtaibai83egon25
subn:返回一个元组,第二个元素是替换的次数
ret=re.subn('\d+','H','alex83taibai83egon25')
print(ret) #('alexHtaibaiHegonH', 3)
编译一个正则表达式,用编译结果去search、match、findall、finditer 能够节省时间,在多次使用过程中,不会多次编译。
实例:
ret=re.compile('\d+') #已经完成编译,后面操作不再编译
print(ret)
res=ret.findall('alex83taibai83egon25')
print(res)
res=ret.search('alex83taibai83egon25')
print(res.group())
#结果:
re.compile('\\d+')
['83', '83', '25']
83
finditer 返回一个迭代器,所有的结果都在这个迭代器中,需要通过循环+group的形式取值 ,能够节省空间。
实例:
ret=re.finditer('\d+','128shduwer93') #参数:正则表达式,带匹配的字符串
print(ret) #可迭代
for i in ret:
print(i.group())
结果:
128
93
大多数时候,我们想要的数据掺杂在不想要的中间,这时候需要用分组来提取我们想要的内容。
先给出一个例子去了解分组,如下实例:
从字符串 'wahaha' 中可提取出我们想要的内容
import re
s='wahaha'
ret=re.search('<(\w+)>(\w+)(\w+)>',s)
print(ret.group(0)) #所有的结果,0可写可不写
print(ret.group(1)) #数字参数代表取对应分组中的内容
print(ret.group(2))
print(ret.group(3))
结果:
wahaha
a
wahaha
a
findall 也可以取到分组中的内容,有一个特殊的语法:优先显示分组中的内容
ret=re.findall('>(\w+)<',s)
print(ret) #['wahaha']
ret=re.findall('(\w+)',s)
print(ret) #['a', 'wahaha', 'a']
但有的时候不需要分组优先,那么怎么取消分组优先呢?
解决分组优先只需要在分组中加问号:(?:正则表达式)
实例:
ret=re.findall('\d+(\.\d+)?','1.234*2.345')
#分组优先,输出小数点位
print(ret) #['.234', '.345']
#取消分组优先
ret=re.findall('\d+(?:\.\d+)?','1.234*2.345')
print(ret) #['1.234', '2.345']
(\.[\w+]+)
<(\w+)>(\w+)(\w+)>
split :了解即可
ret=re.split('\d+','alex83taibai83egon25') #把匹配到的切割掉 ['alex', 'taibai', 'egon', '']
print(ret)
ret=re.split('(\d+)','alex83taibai83egon25') #加上分组后,将切割掉的内容再补上 ['alex', '83', 'taibai', '83', 'egon', '25', '']
print(ret)
(?P<分组的名字>正则表达式)
上面讲到通过group()里的参数获取匹配内容,这里也可通过分组名获取匹配内容
实例:
s='wahaha'
ret=re.search('>(?P\w+)<',s) #将分组命名为con
print(ret.group(1)) #wahaha
print(ret.group('con')) #wahaha 通过分组名获取匹配内容
有时候,我们可以使用前面的分组,这要求使用这个名字的分组和前面同名分组中的内容匹配的必须一致
s='wahaha'
pattern='<(?P\w+)>(\w+)(?P=tab)>'
ret=re.search(pattern,s)
print(ret) #能够匹配到 <_sre.SRE_Match object; span=(0, 13), match='wahaha'>
反例:当前后不一致时,换成不能匹配到
s='wahaha'
pattern='<(?P\w+)>(\w+)(?P=tab)>'
ret=re.search(pattern,s)
print(ret) #None
#精准到整数,过滤掉小数
ret=re.findall(r"\d+\.\d+|\d+","1-2*(60+(-40.35/5)-(-4*4))")
print(ret)#['1', '2', '60', '40.35', '5', '4', '4']
#分组优先显示整数
ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*4))")
print(ret)#['1', '2', '60', '', '5', '4', '4']
ret.remove('')#去掉空值
print(ret)#['1', '2', '60', '5', '4', '4']
s='wahaha'
ret=re.search('>(?P\w+)<',s) #将分组命名为con
print(ret.group('con')) #wahaha 通过分组名获取匹配内容
用正则表达式爬取豆瓣电影