正则表达式

发布于:2025-03-27 ⋅ 阅读:(22) ⋅ 点赞:(0)

规则

\d 匹配任意数字

\D 匹配任意非数字

\s 匹配任意空白字符

\S 匹配任意非空白字符

\w 匹配任意字母、数字或下划线

\W 匹配任意非字母、数字或下划线

. 匹配任意字符

^ 匹配字符串的开头

$ 匹配字符串的末尾

[] 匹配括号内的任意字符

[^] 匹配不在括号内的任意字符

* 匹配前面的字符0次或多次

+ 匹配前面的字符1次或多次

? 匹配前面的字符0次或1次

{n} 匹配前面的字符恰好n次

{n,} 匹配前面的字符至少n次

{n,m} 匹配前面的字符至少n次,至多m次

| 匹配两个或多个表达式中的任意一个

(...) 匹配括号内的表达式,并记住匹配的文本

(?...) 匹配括号内的表达式,但是不记住匹配的文本

(?P<name>...) 匹配括号内的表达式,并记住匹配的文本,并把匹配的文本保存到一个名字为name的组中

(?P=name) 匹配之前的命名组name匹配的文本

(?#...) 注释,不参与匹配

(?=...) 正向肯定界定符,在...前面的字符必须匹配

(?!...) 正向否定界定符,在...前面的字符不能匹配

(?<=...) 反向肯定界定符,在...后面的字符必须匹配

(?<!...) 反向否定界定符,在...后面的字符不能匹配

(?imxs) 正则表达式选项,i表示忽略大小写,m表示多行匹配,s表示使.匹配所有字符,x表示忽略空格和#后面的注释

(?-imxs) 正则表达式选项,-表示关闭选项

1. 字符匹配

正则表达式在网络爬虫、数据分析中有着广泛使用,掌握正则表达式能够达到事半功倍的效果。

1.1 方法和功能

方法 功能
match() 判断一个正则表达式是否从开始处匹配一个字符串
search() 遍历字符串,找到正则表达式匹配的第一个位置,返回匹配对象
findall() 遍历字符串,找到正则表达式匹配的所有位置,并以列表的形式返回。如果给出的正则表达式中包含子组,就会把子组的内容单独返回,如果有多个子组就会以元组的形式返回。
finditer() 遍历字符串,找到正则表达式匹配的所有位置,并以迭代器的形式返回
  • hqyj匹配文本中的hqyj

 import re
 text="hqyj牛皮6666,hqyj有个老师也牛皮666"
 data=re.findall("hqyj",text)
 print(data)#['hqyj', 'hqyj']
  • [hqyj]匹配h或者q或者y或者j字符

 import re
 text="hqyj牛皮6666,hqyj有个老师也牛皮666"
 data=re.findall("[hqyj]",text)
 print(data)#['h', 'q', 'y', 'j', 'h', 'q', 'y', 'j']
 import re
 text="hqyj牛皮6666,hqyj有个老师也牛皮666"
 data=re.findall("[hqyj]牛",text)
 print(data)#['j牛']
  • [^hqyj]匹配除了hqyj以外的其他字符

 import re
 text="hqyj牛皮6666,hqyj有个老师也牛皮666"
 data=re.findall("[^hqyj]",text)
 print(data)#['牛', '皮', '6', '6', '6', '6', ',', '有', '个', '老', '师', '也', '牛', '皮', '6', '6', '6']
 ​
  • [a-z]匹配a~z的任意字符([0-9]也可以)

 import re
 ​
 text = "hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
 data = re.findall("[a-z]hqyj", text)
 print(data)  # ['chqyj']
  • .匹配除了换行符以外的任意字符

 import re
 text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
 data=re.findall(".hqyj",text)
 print(data)#[',hqyj', 'chqyj']
 import re
 text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
 data=re.findall(".+hqyj",text) #贪婪匹配(匹配最长的)
 print(data)#['hqyj牛皮6666,hqyj有个老师abchqyj']
 import re
 text="hqyj牛皮6666,hqyj有个老师abchqyj也牛皮666"
 data=re.findall(".?hqyj",text)
 print(data)#['hqyj', ',hqyj', 'chqyj']

1.2 特殊字符

特殊字符 含义
\d 匹配任何十进制数字;相当于类 [0-9]
\D 与 \d 相反,匹配任何非十进制数字的字符;相当于类 0-9
\s 匹配任何空白字符(包含空格、换行符、制表符等);相当于类 [ \t\n\r\f\v]
\S 与 \s 相反,匹配任何非空白字符;相当于类 \t\n\r\f\v
\w 匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式[a-zA-Z0-9_]
\W 于 \w 相反 (注:re.ASCII 标志使得 \w 只能匹配 ASCII 字符)
\b 匹配单词的开始或结束
\B 与 \b 相反
  • \w 匹配字母数字下划线(汉字)

 import re
 ​
 text = "华清_远见abc 华清hqyj远见 华清牛皮远见"
 data = re.findall(r"华清\w+远见", text)
 print(data)  # ['华清_远见', '华清hqyj远见', '华清牛皮远见']
  • \d匹配数字

 import re
 ​
 text = "hqyj66d6 a1h43d3fd43s43d4 "
 data = re.findall(r"d\d", text)  # 只匹配一个数字
 print(data)  # ['d6', 'd3', 'd4', 'd4']
 import re
 ​
 text = "hqyj66d6 a1h43d3fd43s43d4 "
 data = re.findall(r"d\d+", text)
 print(data)  # ['d6', 'd3', 'd43', 'd4']
  • \s匹配任意空白符 包括空格,制表符等等


 import re
 ​
 text = "hqyj666  jack karen 666"
 data = re.findall(r"\sj\w+\s", text)
 print(data)  # [' jack ']
#[] 匹配括号内的任意字符
#[a-z],[1-9],[A-Z] 匹配指定范围内的任意字符
#[^a-z] 匹配不在指定范围内的任意字符
#[a-zA-Z0-9] 匹配任意字母、数字或下划线

x = re.findall("[abc]", "abcagdfasafaadfaafa")  #查找所有小写字母
print(x)  #['a', 'a', 'a'] #['a', 'b', 'c', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']

#[^] 匹配不在括号内的任意字符
#[^a-zA-Z0-9] 匹配任意非字母、数字或下划线
x = re.findall("[^abc]", "abcagdfasafaadfaafa")  #查找所有非小写字母
print(x)  #['g', 'd', 'f', 's', 'f', 'd', 'f', 'f']

# . 匹配任意字符,点代表任意字符,
x = re.findall(".a", "abcagdfasafaadfaafa")  #查找所有以a结尾的字符
print(x)  #['ca', 'fa', 'sa', 'fa', 'fa', 'fa']

# \d 匹配任意数字
x = re.findall("\d","fds55fsdaf66saf77")
print(x) #['5', '5', '6', '6', '7', '7']

# \D 匹配任意非数字
x = re.findall("\D","fds55fs")
print(x) #['f', 'd', 's', 'f', 's']
x = re.findall("\Ds","fds55fs")
print(x) #['ds', 'fs']

# \s 匹配任意空白字符
x = re.findall("\s","fds 55fs daf6 6saf77")
print(x) #[' ', ' ', ' ']
x = re.findall("\sd","fds d55fs daf6 6saf77")
print(x) #[' d', ' d']

#\b 匹配单词边界,指的是一个单词的开始或结束,也就是单词的开头或结尾,单词边界的位置是不固定的,可以出现在单词中间,但是不能出现在单词的中间
x = re.findall("\b","fds 55fs daf6 6saf77")
print(x)

#+ 匹配前面的字符1次或多次
x =re.findall("[1-9]+","15616afdaf454585ssdgf")
print(x) 


#以.jpg结尾
x = re.findall(r"^电话\d+","电话15gfdg电话465")
print(x) #电话15

#以.jpg结尾
x = re.findall(r"\d\.jpg$","电话15gfdg.jpg 电话465.jpg")
print(x)

2. 数量控制

控制匹配规则的重复次数~

2.1 *重复0次或多次

 import re
 text="华清远见 华清666远见"
 data=re.findall("华清6*远见",text)
 print(data)#['华清远见', '华清666远见']

2.2 +重复1次或多次

 import re
 text="华清远见 华清666远见 华清6远见"
 data=re.findall("华清6+远见",text)
 print(data)#['华清666远见', '华清6远见']

2.3 ?重复1次或0次

 import re
 text="华清远见 华清666远见 华清6远见"
 data=re.findall("华清6?远见",text)
 print(data)#['华清远见', '华清6远见']

2.4 {n}重复n次

 import re
 text="华清远见 华清666远见 华清6远见"
 data=re.findall("华清6{3}远见",text)
 print(data)#['华清666远见']

2.5 {n,}重复n次或多次

 import re
 text="华清远见 华清666远见 华清6远见 华清66远见"
 data=re.findall("华清6{2,}远见",text)
 print(data)#['华清666远见', '华清66远见']

2.6 {n,m}重复n到m次

 import re
 text="华清远见 华清666远见 华清6远见 华清66远见"
 data=re.findall("华清6{0,2}远见",text)
 print(data)#['华清远见', '华清6远见', '华清66远见']

3. 分组

  • ()提取兴趣区域

 import re
 ​
 text = "谢帝谢帝,我要迪士尼,我的电话号码18282832341,qq号码1817696843"
 data = re.findall(r"号码(\d{10,})", text)
 print(data)  # ['18282832341', '1817696843']
 import re
 ​
 text = "谢帝谢帝,我要迪士尼,我的电话号码18282832341,qq号码1817696843"
 data = re.findall(r"(\w{2}号码(\d{10,}))", text)
 print(data)  # ['18282832341', '1817696843']
  • (|)提取兴趣区域(| = or)

 import re
 ​
 text = "第一名张三 第一名物理149分 第一名数学150分 第一名英语148分 第一名总分740分"
 data = re.findall(r"第一名(\w{2,}|\w{2,}\d{2,}分)", text)
 print(data)  # ['张三', '物理149分', '数学150分', '英语148分', '总分740分']

4. 开始和结束

  • ^开始

 import re
 text = "hqyj66abc hqyj123"
 data = re.findall(r"^hqyj\d+", text)
 print(data)  # ['hqyj66']
  • $结尾

 import re
 text = "hqyj66abc hqyj123"
 data = re.findall(r"hqyj\d+$", text)
 print(data)  # ['hqyj123']

5. 特殊字符

由于正则表达式中* . \ {} () 等等符号具有特殊含义,如果你指定的字符正好就是这些符号,需要用\进行转义

 import re
 text = "数学中集合的写法是{2}"
 data = re.findall(r"\{2\}", text)
 print(data)  # ['{2}']

6. 常用方法

6.1 re.findall

获取匹配到的所有数据

 import re
 text="hqyj66d6 a1h43d3fd43s43d4 "
 data=re.findall("d\d+",text)
 print(data)#['d6', 'd3', 'd43', 'd4']

6.2 re.match

从字符串的起始位置匹配,成功返回一个对象否则返回none。

匹配成功返回对象,对象的方法:

方法 功能
group() 返回匹配的字符串
start() 返回匹配的开始位置
end() 返回匹配的结束位置
span() 返回一个元组表示匹配位置(开始,结束)
 import re
 ​
 # 在起始位置匹配,并返回一个包含匹配 (开始,结束) 的位置的元组
 print(re.match('www', "www.python.com").span())     # (0, 3)
 print(re.match('www', "www.python.com").start())    # 0
 print(re.match('www', "www.python.com").end())      # 3
 # 不在起始位置匹配
 print(re.match('com', "www.python.com"))            # None

6.3 re.search

扫描整个字符串并返回第一个成功匹配的字符串。成功返回一个对象否则返回none

 import re
 ​
 # 在起始位置匹配
 print(re.search('www', 'www.hqyj.com').span())  # (0, 3)
 # 不在起始位置匹配
 print(re.search('com', 'www.hqyj.com').span())  # (9, 12)

6.4 re.sub

替换匹配成功的字符

类似与字符串的replace函数

 import re
 ​
 text = "以前华清远见在四川大学旁边,现在华清远见在西南交大旁边"
 data = re.sub("华清远见", "北京华清远见科技集团成都中心", text)
 print(data)  # 以前北京华清远见科技集团成都中心在四川大学旁边,现在北京华清远见科技集团成都中心在西南交大旁边

6.5 re.split

根据匹配成功的位置对字符串进行分割

 import re
 ​
 text = "python is   very easy"
 data = re.split(r"\s{1,}", text)
 print(data)  # ['python', 'is', 'very', 'easy']

6.6 re.finditer

类似findall 但是不会全部返回出来 而是返回迭代器(比如匹配成功了10万个 全部返回就很吃内存了)

 
import re
 ​
 text = "python is   very easy"
 data = re.findall(r"\w+", text)
 print(data)  # ['python', 'is', 'very', 'easy']
 import re
 ​
 text = "python is   very easy"
 data = re.finditer(r"\w+", text)
 print(data)
 for el in data:
     print(el.group())

7. 常见正则

 QQ号:[1 - 9][0 - 9]{4, }(腾讯QQ号从10000开始)
 帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
 手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
 Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
 密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
 身份证号(15位、18位数字):^\d{15}|\d{18}$
 短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$