正则也是各种计算机语言通用的一种技术,本文主要讲解如何使用Python的re模块处理和使用正则表达式,但是对正则表达式的基础不过多阐述,以讲解如何使用Python处理正则为主,如果缺少正则基础知识的朋友可以查看我在PHP专区的正则教程
接下来正式介绍
import re #首先要引入re模块
re.search(r'abc','I love abc') #search方法用来在字符串中搜索表达式第一次出现的位置
#他返回的是一个对象
#<_sre.SRE_Match object; span=(7, 10), match='abc'>
# 表达式要用原始字符串 r 可以省下很多麻烦
#re.search只匹配一次
re.search(r"[abcd]","I love abcba)
#使用()配合\数字是子匹配引用
print(re.search(r"(abc)\1","aaaabcabcccc")) #<_sre.SRE_Match object; span=(3, 9), match='abcabc'>
注意,在[]中,多数匹配符会失效
例如,.匹配除了换行符中的所有字符,但是[.]他就变成了匹配.的字符串
^ - 在[]中有特殊作用
search方法匹配一次,如果想要匹配多个,可以这样使用findall方法
re.findall(r"[a-z]","jsadfljaldsfj")
#他会返回一个列表,里面放着所有匹配到的内容
#['j', 's', 'a', 'd', 'f', 'l', 'j', 'a', 'l', 'd', 's', 'f', 'j']
关于贪婪匹配
str="<html><title>hello</title></html>"
#我想只匹配一个<html>
re.search(r"<.+>",str)
#结果是把<html><title>hello</title></html>全都匹配了
#因为这个str的第一个字符是<,最后一个字符是>,他会尽可能多的匹配
#此时用.+?可以拒绝贪婪匹配
hello
" #我想只匹配一个
re.search(r"<.+>",str) #结果是把
hello
全都匹配了 #因为这个str的第一个字符是<,最后一个字符是>,他会尽可能多的匹配 #此时用.+?可以拒绝贪婪匹配
如果search匹配不到会返回None
如果findall匹配不到会返回[]
如果需要重复使用某个正则表达式,我们可以用re.compile()来将他编译
例如:
import re
pattern=re.compile(r"[a-z]+",re.I) #这里compile的第二参可以传入模式修正符,这里使用的是I修正符即忽略大小写
str1 = "My name is zbp"
str2 = "I'm 22 years old"
print(pattern.findall(str1)) #['My', 'name', 'is', 'zbp']
print(pattern.findall(str2)) #['I', 'm', 'years', 'old']
search和findall的第三参可以传入模式修正符
常用修正符:
I 忽略大小写
S 使得.可以匹配换行
M 多行匹配,但会影响^ $
关于如何获取子匹配内容
我们知道用()可以保存子匹配的内容
对于search方法来说,可以配合()和group()方法获取子匹配
res=re.search(r"(\w+) (\w+)","I love you")
print(res.group()) # I love
print(res.group(1)) # I
print(res.group(2)) # love
这个其实在Python的正则技术中叫做分组
对于findall方法来说,如果有子匹配的话,他会返回一个列表,里面放着的是子匹配的内容;如果正则中只有一个子匹配,那么他是一个列表放着多个字符串;如果有多个子匹配就是一个列表放着多个元祖,元组中放着多个子匹配字符串;
例如
ip="""
23.225.228.2,
23.225.166.3,
192.168.1.100,
171.110.5.1
"""
p=re.compile(r"(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])")
res=p.findall(ip)
print(res)
#结果:
#[('228.', '228', '2'), ('166.', '166', '3'), ('1.', '1', '100'), ('5.', '5', '1')]
因为我上面正则中有3个(),匹配到4个ip,所以返回一个长度为4的列表,里面的元组长度为3;
再如下:
html="""
<center>
<img src="https://mtl.ttsqgs.com/images/img/16571/1.jpg" alt="[Ugirls爱尤物] No.1312 董小姐poppy - 谁的董小姐 写真套图第1张" class="content_img" title="美图录提示:点击图片,查看原尺寸高清大图">
<img src="https://mtl.ttsqgs.com/images/img/16571/2.jpg" alt="[Ugirls爱尤物] No.1312 董小姐poppy - 谁的董小姐 写真套图第2张" class="content_img" title="美图录提示:点击图片,查看原尺寸高清大图">
<img src="https://mtl.ttsqgs.com/images/img/16571/3.jpg" alt="[Ugirls爱尤物] No.1312 董小姐poppy - 谁的董小姐 写真套图第3张" class="content_img" title="美图录提示:点击图片,查看原尺寸高清大图">
<img src="https://mtl.ttsqgs.com/images/img/16571/4.jpg" alt="[Ugirls爱尤物] No.1312 董小姐poppy - 谁的董小姐 写真套图第4张" class="content_img" title="美图录提示:点击图片,查看原尺寸高清大图">
</center>
"""
p=re.compile(r'<img src=\"([^\"]+)\".*?>')
res=p.findall(html)
print(res)
#结果是:
#['https://mtl.ttsqgs.com/images/img/16571/1.jpg', 'https://mtl.ttsqgs.com/images/img/16571/2.jpg', 'https://mtl.ttsqgs.com/images/img/16571/3.jpg', 'https://mtl.ttsqgs.com/images/img/16571/4.jpg']
啊,不好意思,上面的一串html代码好像让大家发现了些什么.....
咱们继续,因为正则中只有一个子匹配,所以列表中的内容不是元组而是字符串。如果不想使用子匹配可以在括号开头加一个?即(?:xxx)
使用了子匹配,他就无法匹配整个正则的内容,此时你可以在整个正则外面包一个括号:
p=re.compile(r'(<img src=\"([^\"]+)\".*?>)')
既能得到完整匹配,又可以得到子匹配
最后在说一下一个很常用的,正则替换
如下
import re
html="""
<center>
<img src="https://mtl.ttsqgs.com/images/img/16571/1.jpg" alt="[Ugirls爱尤物] No.1312 董小姐poppy - 谁的董小姐 写真套图第1张" class="content_img" title="美图录提示:点击图片,查看原尺寸高清大图">
</center>
"""
#现在我要将上面字符串中双引号中的内容替换为#
pattern = re.compile(r"\"(.*?)\"")
html2 = pattern.sub("\"#\"",html)
print(html2)