4 匹配多个字符
代码 | 功能 |
* | 匹配前一个字符出现0次或者无限次,即可有可无 |
+ | 匹配前一个字符出现1次或者无限次,即至少有1次 |
? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
4.1 示例1:*
需求:匹配出一个字符串第一个字母为大小字符,后面都是小写字母并且这些小写字母可 有可无
# * 匹配前一个字符出现0次或者无限次,即可有可无 import re ret = re.match("[A-Z][a-z]*","M") print(ret.group()) ret = re.match("[A-Z][a-z]*","MnnM") print(ret.group()) ret = re.match("[A-Z][a-z]*","Aabcdef") print(ret.group())
运行结果:
M Mnn Aabcdef
4.2 示例2:+
需求:匹配一个字符串,第一个字符是t,最后一个字符串是o,中间至少有一个字符
import re match_obj = re.match("t.+o", "two") if match_obj: print(match_obj.group()) else: print("匹配失败")
运行结果:
two
4.3 示例3:?
需求:匹配出这样的数据,但是https 这个s可能有,也可能是http 这个s没有
match_obj = re.match("https?", "http") if match_obj: print(match_obj.group()) else: print("匹配失败")
运行结果:
http
4.4 示例4:{m}
# {m}: 匹配前一个字符串必须出现m次 match_obj = re.match("ht{2}p", "http") if match_obj: # 获取匹配结果 result = match_obj.group() print(result) else: print("匹配失败")
运行结果:
http
4.5 示例5:{m,n}
# {m, n}: 匹配前一个字符串最少出现m次,最多出现n次 match_obj = re.match("ht{1,3}p", "httttp") if match_obj: # 获取匹配结果 result = match_obj.group() print(result) else: print("匹配失败") # 扩展: {m, }:匹配前一个字符串至少出现m次 match_obj = re.match("ht{2,}p", "htttttp") if match_obj: # 获取匹配结果 result = match_obj.group() print(result) else: print("匹配失败")
运行结果:
匹配失败 htttttp
5 匹配开头和结尾
代码 | 功能 |
^ | 匹配字符串开头, [^指定字符]: 表示除了指定字符都匹配 |
$ | 匹配字符串结尾 |
5.1 示例1:^
# 匹配以数字开头 match_obj = re.match("^\d.*", "1abc") if match_obj: # 获取匹配结果 result = match_obj.group() print(result) else: print("匹配失败")
运行结果:
1abc
5.2 示例2:$
match_obj = re.match(".*\d$", "aa3") if match_obj: # 获取匹配结果 result = match_obj.group() print(result) else: print("匹配失败")
运行结果:
aa3
5.3 示例3:^ 和 $
# 匹配以数字开头中间内容不管以数字结尾 match_obj = re.match("^\d.*\d$", "2asdfa3") if match_obj: # 获取匹配结果 result = match_obj.group() print(result) else: print("匹配失败") # [^指定字符] 表示除了指定字符都匹配 # [^47] 除了4和7都匹配 # ^: 表示以指定字符串开头 # [^]: 表示除了指定字符串都匹配 match_obj = re.match("^\d.*[^47]$", "2asdfa7") if match_obj: # 获取匹配结果 result = match_obj.group() print(result) else: print("匹配失败")
运行结果:
2asdfa3 匹配失败
6 匹配分组
代码 | 功能 |
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num | 引用分组num匹配到的字符串 |
(?P) | 分组起别名 |
(?P=name) | 引用别名为name分组匹配到的字符串 |
6.1 示例1:|
# 水果列表 fruit_list = ['apple', 'banana', 'orage', 'pear', 'peach'] for value in fruit_list: # 根据每一个字符串,使用正则表达式进行匹配 # | 匹配左右任意一个表达式 match_obj = re.match("banana|pear", value) if match_obj: result = match_obj.group() print("我想吃的水果:", result) else: print("我不想吃的水果:", value)
运行结果:
我不想吃的水果: apple 我想吃的水果: banana 我不想吃的水果: orage 我想吃的水果: pear 我不想吃的水果: peach
6.2 示例2:( )
# 匹配出163、126、qq等邮箱 # \.: 表示对正则表达式里面的.进行了转义,变成了一个普通点,只能匹配.字符 # (163|126|qq) 表示一个分组,出现一个小括号就表示一个分组,分组是从1开始的 # 如果出现多个小括号,分组的顺序是从左到右一次排序 match_obj = re.match("[a-zA-Z0-9_]{4,20}@(163|126|qq)\.com", "hello@163.com") if match_obj: # 获取整个匹配的数据,如果使用分组数的化,默认是0 result = match_obj.group(0) # 获取匹配分组数据 type = match_obj.group(1) print(type) print(result) else: print("匹配失败") # "qq:3014587" match_obj = re.match("(qq:)([1-9]\d{4,11})", "qq:666666") if match_obj: result = match_obj.group() print(result) result = match_obj.group(1) print(result) result = match_obj.group(2) print(result) else: print("匹配失败")
运行结果:
163 hello@163.com qq:666666 qq: 666666
6.3 示例3:\num
需求:匹配出hh
match_obj = re.match("<[a-zA-Z1-6]+>.*</[a-zA-Z1-6]+>", "<html>hh</div>") if match_obj: print(match_obj.group()) else: print("匹配失败") match_obj = re.match("<([a-zA-Z1-6]+)>.*</\\1>", "<html>hh</html>") if match_obj: print(match_obj.group()) else: print("匹配失败")
运行结果:
<html>hh</div> <html>hh</html>
需求:匹配出
www.baidu.com
match_obj = re.match("<([a-zA-Z1-6]+)><([a-zA-Z1-6]+)>.*</\\2></\\1>", "<html><h1>www.baidu.com</h1></html>") if match_obj: print(match_obj.group()) else: print("匹配失败")
运行结果:
<html>\<h1>www.baidu.com\</h1>\</html>
6.4 示例4:(?P) (?P=name)
# <html><h1>www.itcast.cn</h1></html> match_obj = re.match("<(?P<name1>[a-zA-Z1-6]+)><(?P<name2>[a-zA-Z1-6]+)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.baidu.com</h1></html>") if match_obj: result = match_obj.group() print(result) else: print("匹配失败")
运行结果:
<html><h1>www.baidu.com</h1></html>
7 python中常用方法介绍
三个函数用于查找匹配match()、search()、findall(),一个函数sub()用于替换,一个函数split()用于切分字符串。
- match():匹配字符串的开头,如果开头匹配不上,则返回None;
- search():扫描整个字符串,匹配后立即返回,不在往后面匹配;
- findall():扫描整个字符串,以列表形式返回所有的匹配值;
- compile():将字符串编译成正则表达式对象,供 match() 、 search() 和findall()函数使用;
- sub():扫描整个字符串,用于替换字符串的某些值;
- split():扫描整个字符串,按照指定分隔符切分字符串;
s1 = 'ab少cd年abc' r2 = re.search('b',s1) r2.group() # b r3 = re.findall('[a|b]',s1) r3.group() # ['a', 'b', 'a', 'b'] r4 = re.findall('f',s1) r4.group() # []
下面我们根据一个爬虫经常见到的html格式数据,使用正则表达式,获取其中的li标签,或者获取其中的href属性,应该怎么做呢?
html = '''<html> <head lang="en"> <title>Title</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div id="content"> <ul id="ul1"> <li>first</li> <li>second</li> <li>third</li> </ul> <ul id="ul2"> <li>alpha</li> <li>beta</li> </ul> </div> <div id="url"> <a href="http:www.baidu.com" title="baidu">baidu</a> <a href="http:www.csdn.net" title="csdn">csdn</a> </div> </body> </html> ''' # 获取li标签 re.findall('<li>(.*?)</li>',html) # ['first', 'second', 'third', 'alpha', 'beta'] # 获取href属性 re.findall('<a href="(.*?)" ',html) # ['http:www.baidu.com', 'http:www.csdn.net']
操作其实很简单,固定写法:首尾照抄字符串源代码,我们想要的东西使用()小括号,括起来,里面写上 .*?
上面提到了一个.与.?,其中.表示贪婪匹配,.?表示非贪婪匹配。
- . 可以匹配除了换行符以外的所有字符;
- *表示匹配前面的字符无限次;
- ?前面紧挨的元素,最多匹配一次;
# '\D{3,5}'表示匹配非数字3-5次。 s3 = '12one34two56three78four' # 这里没有指定最大匹配次数,因此默认会替换所有的匹配值 re.sub('\D{3,5}','字母',s3) # 12字母34字母56字母78字母 # 这里指定最大匹配次数count=2,因此只会替换前2个匹配值 re.sub('\D{3,5}','字母',s3,2) # 12字母34字母56three78four # 如果count=3,则会替换3个匹配值 re.sub('\D{3,5}','字母',s3,3) # 12字母34字母56字母78four # '\D'表示匹配非数字 s4 = '136-3456-7413' # 这里如果不指定“最大分割次数”,则是不限次数切分 re.split('\D',s4) # ['136', '3456', '7413'] # 如果指定最大分割次数maxsplit=1,那么就只以第一个分隔符,进行切分 re.split('\D',s4,1) # ['136', '3456-7413']