crawler-09 Re 正则表达式入门

crawler-09 Re 正则表达式入门

一、概念

  正则表达式, Regular Expression (缩写 regex),是用来简洁表达一组字符串的表达式;其特点是简洁,一

行胜千言。

  正则表达式是用来简洁表达一组字符串的表达式,是一种通用的字符串表达框架。正则表达式是一种针对字符

串表达“简洁”和“特征”思想的工具 正则表达式可以用来判断某字符串的特征归属。

正则表达式在文本处理中十分常用:

  表达文本类型的特征(病毒、入侵等) 同时查找或替换一组字符串 匹配字符串的全部或部分 …… 主要应用在

字符串匹配中。

二、正则表达式语法

  正则表达式语法由字符和操作符构成。

1、常用操作符

操作符 说明 实例
. 表示任何单个字符
[ ] 字符集,对单个字符给出取值范围 [abc]表示a、b、c;[a-z]表示小写a到z的单个字符
[^ ] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
* 前一个字符0次或无限次扩展 abc*表示ab、abc、abcc、abcccc等
+ 前一个字符1次或者无限次扩展 abc+表示abc、abcc、abcccc等
前一个字符0次或1次扩展 abc?表示ab、abc
\ 左右表达式任意一个 abc\ def表示abc或者def
{m} 扩展前一个字符m次 ab{2}c表示abbc
{m,n} 扩展前一个字符m至n次(包含n) ab{1,2}c表示abc、abbc
^ 匹配字符串的开头 ^abc表示以abc开头的字符串abc
$ 匹配字符串的结尾 abc$表示已abc结尾的字符串abc
( ) 分组标记,内部只能使用 \ 操作符 (abc)表示abc,(abc\ def)表示abc、def
\d 数字,等价于[0-9]
\w 单词字符,等价于[A-Za-z0-9_]

2、经典正则表达式实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1)由26个字母组成的字符
^[A‐Za‐z]+$

2)由26个字母和数字组成的字符串
^[A‐Za‐z0‐9]+$

3)整数形式的字符串
^‐?\d+$

4)正整数形式的字符串
^[0‐9]*[1‐9][0‐9]*$

5)中国境内邮政编码,6位
#意思是邮政编码的首位一定是1-9而不是0;后5位则是任意数字
[1‐9]\d{5}

6)匹配中文字符
[\u4e00‐\u9fa5]

7)国内电话号码,010‐68913536
#电话号有两种格式,另一种是0397-2865666这种格式
\d{3}‐\d{8}|\d{4}‐\d{7}

3、匹配ip地址的正则表达式

1
2
3
4
5
6
7
8
9
10
11
1)粗略写法
\d+.\d+.\d+.\d+ 

2)精确写法
\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}

3)精确写法
0‐99:[1‐9]?\d 
100‐199: 1\d{2}
200‐249: 2[0‐4]\d
250‐255: 25[0‐5]

Re库的基本使用

  Re库是Python的标准库,主要用于字符串匹配;调用方式:

1
import re

1、正则表达式的表示类型

1)raw string类型(原生字符串类型) ;re库采用raw string类型表示正则表达式,表示为: r’text’ 例如:

1
2
r'[1‐9]\d{5}' 
r'\d{3}‐\d{8}|\d{4}‐\d{7}'

注意:raw string是不包含对转义符再次转义的字符串。

2)string类型(字符串类型);例如:

1
2
'[1‐9]\\d{5}' 
'\\d{3}‐\\d{8}|\\d{4}‐\\d{7}'

建议:当正则表达式包含转义符时,应该使用raw string,否则会很繁琐。

Re库主要功能函数

函数 说明
re.search() 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象
re.match 从一个字符串的开始位置起匹配正则表达式,返回match对象
re.findall() 搜索字符串,以列表类型返回全部能匹配的子串
re.split() 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型
re.finditer() 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
re.sub() 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
1
2
3
4
5
re.search(pattern,string,flags=0)

∙ pattern : 正则表达式的字符串或原生字符串表示
∙ string : 待匹配字符串
∙ flags : 正则表达式使用时的控制标记

1)flags : 正则表达式使用时的控制标

常用标记 说明
re.I re.IGNORECASE 忽略正则表达式的大小写,[A‐Z]能够匹配小写字符
re.M re.MULTILINE 正则表达式中的^操作符能够将给定字符串的每行当作匹配开始
re.S re.DOTALL 正则表达式中的.操作符能够匹配所有字符,默认匹配除换行外的所有字符

2)实例

1
2
3
4
5
6
7
8
#在字符串'abcd 212000'中匹配出邮编
import re
match=re.search(r'[1-9]\d{5}','abcd 212000')
if match:
print(match.group(0)) #match对象通常用group()函数来提取数据

#输出
212000

2、re.match

1
2
3
4
5
re.match(pattern,string,flags=0)

∙ pattern : 正则表达式的字符串或原生字符串表示
∙ string : 待匹配字符串
∙ flags : 正则表达式使用时的控制标记

1) flags和re.search()里的一样,其他参数也一样

2)实例

1
2
3
4
5
6
7
8
9
10
import re
match=re.match(r'[1-9]\d{5}','abcd 212000')
if match:
print(match.group(0))
print(match.group(0))

#执行结果
AttributeError: 'NoneType' object has no attribute 'group'
报错,说是没有这个类型,实际上match这个变量是空的,空变量自然不能调用group。
match是空的,原因是re.match函数是从起始位置开始匹配,起始位置是abcd而不是邮编,所以匹配无结果,返回的值便是空的。

3)实例

1
2
3
4
5
6
7
8
#判断字符串'212000 abcdefg'的起始位置是否为邮编
import re
match=re.match(r'[1-9]\d{5}','212000 abcdefg')
if match:
print(match.group(0))

#输出
212000

3、re.findall()

1
2
3
4
5
re.findall(pattern,string,flags=0)

∙ pattern : 正则表达式的字符串或原生字符串表示
∙ string : 待匹配字符串
∙ flags : 正则表达式使用时的控制标记

1)实例

1
2
3
4
5
6
import re
ls=re.findall(r'[1-9]\d{5}','212000abcdefg 202222abc')
print(ls)

#输出
['212000', '202222']

4、re.split()

1
2
3
4
5
6
re.split(pattern,string,maxsplit=0,flags=0)

∙ pattern : 正则表达式的字符串或原生字符串表示
∙ string : 待匹配字符串
∙ maxsplit: 大分割数,剩余部分作为后一个元素输出
∙ flags : 正则表达式使用时的控制标记

1)实例

1
2
3
4
5
6
7
8
9
import re
print(re.split(r'[1-9]\d{5}','212000abcdefg 202222abc'))
print("===================================")
print(re.split(r'[1-9]\d{5}','2120

#输出
['', 'abcdefg ', 'abc']
===================================
['', 'abcdefg 202222abc']

5、re.finditer()

1
2
3
4
5
re.finditer(pattern,string,flags=0)

∙ pattern : 正则表达式的字符串或原生字符串表示
∙ string : 待匹配字符串
∙ flags : 正则表达式使用时的控制标记

1)实例

1
2
3
4
5
6
7
8
9
#用for循环可以迭代地获取结果
import re
for m in re.finditer(r'[1-9]\d{5}','212000abcdefg 202222abc'):
if m:
print(m.group(0))

#输出
212000
202222

6、re.sub()

1
2
3
4
5
6
7
re.sub(pattern,repl, string,count=0,flags=0)

∙ pattern : 正则表达式的字符串或原生字符串表示
∙ repl: 替换匹配字符串的字符串
∙ string : 待匹配字符串
∙ count : 匹配的大替换次数
∙ flags : 正则表达式使用时的控制标记

1)实例

1
2
3
4
5
import re
print(re.sub(r'[1-9]\d{5}','pppppp','212000abcdefg 202222abc'))

#结果
ppppppabcdefg ppppppabc

Re库的另一种等价用法

  Re库的上述用法是函数式用法,例如:rst=re.search(r’[1-9]\d{5}’,’abcd 212000’),这里的r’[1-9]\d{5}’只是正则表达式通俗的表示(可以用字符串类型或者原生字符串类型),它需要通过编译之后,才能成为python认可的真正意义上的正则表达式。

  因此,上述Re库的函数式用法,实际上是一次性操作,即用到一次Re库就编译一次,如果需要多次使用,那么这样效率也比较低。

  Re库的另一种等价用法是:面向对象用法,是先把字符串或者原生字符串编译成正则表达式类型的pattern对象,然后进行多次操作。这种方式的好处是,一次编译,多次使用,可以加速程序运行。

1、re.compile()函数

  将正则表达式的字符串形式编译成正则表达式对象。

1
2
3
4
regex = re.compile(pattern,flags=0)

∙ pattern : 正则表达式的字符串或原生字符串表示
∙ flags : 正则表达式使用时的控制标记

2、实例:

1
2
3
4
5
6
7
import re
pat=re.compile(r'[1-9]\d{5}')
rst=pat.search('abcd 212000') #使用时就无需再加pattern参数了
print(rst.group(0))

#输出
212000

Re库的match对象

  Match对象是一次匹配的结果,包含匹配的很多信息,这些信息可以用match对象直接调用出来,例如其属性、函数等。

1、实例

1
2
3
4
5
6
7
8
9
import re
match=re.search(r'[1-9]\d{5}','abcd 100085')
if match:
print(match.group(0))
print(type(match))

#输出
100085
<class 're.Match'>

2、match对象的属性

属性 说明
.string 待匹配的文本
.re 匹配时使用的patter对象(正则表达式)
.pos 正则表达式搜索文本的开始位置
.endpos 正则表达式搜索文本的结束位置

3、match对象的方法

方法 说明
.group(0) 获得匹配后的字符串
.start() 匹配字符串在原始字符串的开始位置(下标)
.end() 匹配字符串在原始字符串的结束位置(下标)
.span() 返回(.start(), .end())

4、综合实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import re
m=re.search(r'[1-9]\d{5}','abcd212000 efgh212003')

print("m.string: ",m.string)
print("m.re: ",m.re)
print("m.pos: ",m.pos)
print("m.endpos: ",m.endpos)

print("m.group(0): ",m.group(0))
print("m.start(): ",m.start())
print("m.end(): ",m.end())
print("m.span(): ",m.span())

#运行结果
m.string: abcd212000 efgh212003
m.re: re.compile('[1-9]\\d{5}') #程序认为经过compile编译过的才是正则表达式
m.pos: 0
m.endpos: 21
m.group(0): 212000 #search()函数只匹配一个结果,finditer()函数可以返回所有结果
m.start(): 4
m.end(): 10
m.span(): (4, 10)

Re库的贪婪匹配和最小匹配

1、实例

1
2
3
4
5
6
import re
match=re.search(r'PY.*N','PYANBNCNDN')
print(match.group(0))

#输出
PYANBNCNDN

  如上,此情况下,PY.*N可以匹配PYAN,也可以匹配’PYANBN或者PYANBNCN或者PYANBNCNDN,那么究竟会匹配到哪个呢?答案是PYANBNCNDN。

  Re库默认采用贪婪匹配,即输出匹配长的子串。

2、如何使用最小匹配

  上例中,如何输出短的子串呢?

1
2
3
4
5
6
import re
match=re.search(r'PY.*?N','PYANBNCNDN')
print(match.group(0))

#输出
PYAN

3、最小匹配操作符

操作符 说明
*? 前一个字符0次或无限次扩展,最小匹配
+? 前一个字符1次或无限次扩展,最小匹配
?? 前一个字符0次或1次扩展,最小匹配
{m,n}? 扩展前一个字符m至n次(含n),最小匹配

  只要长度输出可能不同的,都可以通过在操作符后增加问号?变成最小匹配。

Re库总结

1pjR2V.png

欢迎打赏,谢谢
------ 本文结束------
0%