Python spider入门_2 Python 正则表达式 re 模块
0 前言
python 自1.5 版本起增加了 re 模块,re 模块使 python 拥有全部的正则表达式功能。
python 是自带 re 库的。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。(现在你可能看不懂,但后面就懂了)
接下来我会介绍一些 python 中常用的正则表达式处理函数。
参考网站:Python 正则表达式 | 菜鸟教程 (runoob.com)
1 re.match函数
他尝试从字符串起始位置进行匹配,如果不是起始位置匹配成功的话,match() 就返回 none 。
函数语法:
re.match(pattern, string, flags=0)
函数参数说明:
参数 |
描述 |
pattern |
匹配的正则表达式 |
string |
要匹配的字符串 |
flags |
标志位(但愿你没有忘记) |
匹配成功 re.match 方法返回一个匹配的对象,否则返回 None 。
我们可以使用 group(num) 或group() 匹配对象函数来获取正则表达式。组的存在与顺序是按照你正则表达式的括号 () 存在与顺序决定的
匹配对象方法 |
描述 |
group(num=0) |
匹配整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应的元组 |
groups() |
返回一个包含所有小组字符串的的元组,从 1 到所含的小组号 |
还可以给group添加名字,此时,名字等同于小组号,在正则表达式的对应 () 中最开始添加 ?P 就可以了,把“value”改成你想要的。
例子 1 :
1 2 3 4 5 6 7
| import re
pattern1 = 'cat' pattern2 = 'the' str1 = 'The cat sit on the mat.'
print(re.match(pattern1, str1)) print(re.match(pattern2, str1)) print(re.match(pattern2, str1, flags=re.I)) print(re.match(pattern2, str1, flags=re.I).span())
|
运行结果:
1 2 3 4
| None None <re.Match object; span=(0, 3), match='The'> (0, 3)
|
例子 2 :
1 2 3 4 5 6 7 8 9 10 11 12 13
| import re
line = "Cats are smarter than dogs"
matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)
if matchObj: print("matchObj.group() : ", matchObj.group()) print("matchObj.group(1) : ", matchObj.group(1)) print("matchObj.group(2) : ", matchObj.group(2)) print("matchObj.groups() : ", matchObj.groups()) else: print("No match!!")
|
运行结果:
1 2 3 4
| matchObj.group() : Cats are smarter than dogs matchObj.group(1) : Cats matchObj.group(2) : smarter matchObj.groups() : ('Cats', 'smarter')
|
例子3:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import re
line = "Cats are smarter than dogs"
matchObj = re.match(r'(?P<v1>.*) are (?P<v2>.*?) .*', line, re.M | re.I)
if matchObj: print("matchObj.group() : ", matchObj.group()) print("matchObj.group(1) : ", matchObj.group('v1')) print("matchObj.group(2) : ", matchObj.group(2)) print("matchObj.groups() : ", matchObj.groups()) else: print("No match!!")
|
运行结果:
1 2 3 4
| matchObj.group() : Cats are smarter than dogs matchObj.group(1) : Cats matchObj.group(2) : smarter matchObj.groups() : ('Cats', 'smarter')
|
2 re.search方法
扫描整个字符串并返回第一个成功的匹配
函数语法:
re.serach(pattern, string, flag=0)
例子 1 :
1 2 3 4 5 6 7 8 9 10
| import re
pattern1 = 'cat' pattern2 = 'the' str1 = 'The cat sit on the mat.'
print(re.search(pattern1, str1)) print(re.search(pattern2, str1)) print(re.search(pattern2, str1, flags=re.I)) print(re.search(pattern2, str1, flags=re.I).span())
|
运行结果:
1 2 3 4
| <re.Match object; span=(4, 7), match='cat'> <re.Match object; span=(15, 18), match='the'> <re.Match object; span=(0, 3), match='The'> (0, 3)
|
例子 2 :
1 2 3 4 5 6 7 8 9 10 11 12 13
| import re
line = "Cats are smarter than dogs"
searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I)
if searchObj: print("searchObj.group() : ", searchObj.group()) print("searchObj.group(1) : ", searchObj.group(1)) print("searchObj.group(2) : ", searchObj.group(2)) print("searchObj.groups() : ", searchObj.groups()) else: print("No search!!")
|
运行结果:
1 2 3 4
| searchObj.group() : Cats are smarter than dogs searchObj.group(1) : Cats searchObj.group(2) : smarter searchObj.groups() : ('Cats', 'smarter')
|
3 re.match 和 re.search 的区别
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式(pattern),则匹配失败,函数返回 None ;而 re.search 匹配整个字符串,直到找到一个匹配。
例子:
1 2 3 4 5 6 7 8 9 10
| import re
line = "Cats are smarter than dogs" pattern1 = 'dogs'
matchObj = re.match(pattern1, line) searchObj = re.search(pattern1, line)
print(matchObj) print(searchObj)
|
运行结果:
1 2
| None <re.Match object; span=(22, 26), match='dogs'>
|
4 检索和替换
re 模块提供 re.sub 用于替换字符串中的匹配项
函数语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数 |
描述 |
pattern |
正则中的模式字符串 |
repl |
替换的字符串,也可为一个函数 |
string |
要被查找替换的原始字符串 |
count |
模式匹配后替换的最大次数,默认 0 表示替换所有的匹配 |
例子:
1 2 3 4 5 6 7 8 9 10 11
| mport re
phone = "2004-959-559 # 这是一个国外电话号码"
num = re.sub(r'#.*$', "", phone) print("电话号码是: ", num)
num = re.sub(r'\D', "", phone) print("电话号码是 : ", num)
|
运行结果:
1 2
| 电话号码是: 2004-959-559 电话号码是 : 2004959559
|
4.1 repl参数可以是一个函数
例子:
1 2 3 4 5 6 7 8 9 10 11 12
| import re
line = "www123eee4rrr56"
def r1(x): value = int(x.group('value')) return str(2 * value)
s = re.sub('(?P<value>\d+)', r1, line) print(s)
|
运行结果:
4.2 re.compile函数
用于生成一个正则表达式,可供 match() 和 search() 使用。
语法格式:
re.compile(pattern[, flags])
参数 |
描述 |
pattern |
一个字符串形式的正则表达式 |
flags |
可选,标志,但愿你没忘记 |
例子 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| line = "www123eee4rrr56"
a = re.compile('\d+')
r1 = a.match(line) print(r1) r2 = a.match(line, 3) print(r2) r3 = a.match(line, 4, 10) print(r3) print(r3.start()) print(r3.end())
s1 = a.search(line) print(s1) s2 = a.search(line, 6) print(s2)
|
运行结果:
1 2 3 4 5 6 7
| None <re.Match object; span=(3, 6), match='123'> <re.Match object; span=(4, 6), match='23'> 4 6 <re.Match object; span=(3, 6), match='123'> <re.Match object; span=(9, 10), match='4'>
|
Tips:
start() 方法和 end() 方法都是对于组group而言的,直接使用时,默认为 start(0) 和 end(0) ,即 group(0) 的起始位和终止位
例子 2:
1 2 3 4 5 6 7 8 9 10 11 12 13
| import re
pattern1 = re.compile('([a-z]+) ([a-z]+)', re.I) line = "Hello World python gear"
m = pattern1.match(line)
print(m) print(m.group()) print(m.span())
print(m.group(1)) print(m.span(1))
|
运行结果:
1 2 3 4 5
| <re.Match object; span=(0, 11), match='Hello World'> Hello World (0, 11) Hello (0, 5)
|
4.3 findall
找到字符串匹配正则表达式的所有子串,返回一个列表。如果由多个匹配模式,则返回一个元组列表。
区别:match 和 search 是匹配一次,而 findall 是匹配所有。
语法格式:
findall(string[, pos[, endpos]])
re.findall(pattern, string[, pos[, endpos])
参数 |
解释 |
string |
待匹配的字符串 |
pos |
可选,字符串起始位置指定,默认为零 |
endpos |
可选,字符串终止位置指定,默认为字符串的长度 |
例子1(返回列表):
1 2 3 4 5 6 7 8 9 10 11
| import re
line = "www123eee4rrr56"
a = re.compile('\d+')
r1 = a.findall(line) r2 = a.findall(line, 0, 14)
print(r1) print(r2)
|
1 2
| ['123', '4', '56'] ['123', '4', '5']
|
例子2(返回元组列表):
1 2 3 4 5 6 7 8 9 10 11
| import re
line = "we have longitude = 121° and latitude = 30°"
a = re.compile('(\w+) = (\d+°)')
r1 = a.findall(line) r2 = re.findall('(\w+) = (\d+)', line)
print(r1) print(r2)
|
1 2
| [('longitude', '121°'), ('latitude', '30°')] [('longitude', '121'), ('latitude', '30')]
|
4.4 re.finditer
类似 findall,查找字符串中所有符合正则表达式的子串,并把它们作为一个迭代器返回。
语法格式:
re.finditer(pattern, string, fiags=0)
例子:
1 2 3 4 5 6 7 8 9 10 11
| import re
line = "we have longitude = 121° and latitude = 30°"
a = re.compile('(\w+) = (\d+°)')
r1 = a.finditer(line) print(r1)
for i in r1: print(i.groups())
|
1 2 3
| <callable_iterator object at 0x000002B69F1F93F0> ('longitude', '121°') ('latitude', '30°')
|
4.5 re.split
split 方法按匹配的子串将字符串分割后返回列表
语法格式:
re.split(pattern, string[, maxtype=0, flags=0])
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import re
line = 'unlimited blade works.'
patt0 = re.compile('\w+') patt1 = re.compile('\W+') patt2 = re.compile('(\W+)')
r0 = patt0.split(line) r1 = patt1.split(line) r2 = patt2.split(line) r3 = re.split('\W+', line, 1) r4 = re.split('(\W+)', line, 1)
print(r0) print(r1) print(r2) print(r3) print(r4)
|
1 2 3 4 5
| ['', ' ', ' ', '.'] ['unlimited', 'blade', 'works', ''] ['unlimited', ' ', 'blade', ' ', 'works', '.', ''] ['unlimited', 'blade works.'] ['unlimited', ' ', 'blade works.']
|
5 可选标志符 Flags
标志符 |
描述 |
re.I |
使匹配对大小写不敏感 |
re.L |
使本地化识别 (local-aware) 匹配 |
re.M |
多行匹配,影响 ^ 和 $ |
re.S |
使 . 匹配包括换行在内的所有字符 |
re.U |
根据 Unicode 字符集解析字符,影响 \w,\W,\b ,\B |
re.X |
该标志通过给予你更灵活的形式以便你将正则表达式写得更容易被理解 |