朴素正则

爬虫的时候经常会用正则匹配标签中的内容,整理了re库一些常用的函数:

用于匹配的函数

match()search() 函数是比较常用的两个函数,也很容易混淆。虽然他们感觉上很相似,但实际上匹配策略是不同的。

1
2
3
4
5
6
7
8
9
10

# match() 和 search() 的区别
import re

s = "0731-8888888"
pat=r"(\d-\d)"
re.match(pat, s)
>>>None
re.search(pat, s)
>>><re.Match object; span=(3, 6), match='1-8'>

match严格地从行起始匹配,不可以从字符串中间开始;search可以从字符串中间开始匹配,返回第一个匹配上的结果。检索完成之后,如果匹配成功返回上方例子所示的re.Match object 。

获取匹配字符串结果
1
2
3
4
5
6
7
8
9
10
11
pat1=r"(\d).*(\d-\d)"

re.search(pat1,s).group(0)
>>> 0
re.search(pat1,s).groups()
>>> ('0', '1-8')
match=re.seatch(pat1,s)
match[0],match[1],match[2]
>>> 0731-8 0 1-8
s[match.end(1):match.start(2)]
>>> 73

re.match obj 和迭代器操作有些相似,比如,可以通过索引获取匹配的结果,还有和迭代完全一样的.start().end()。但输出他本身是不能得到字符串的。将匹配字符串内容打印可以使用两种方法:索引和.group()函数

group(n)函数的作用是返回匹配内容的第n组字符串。patter通过圆括号分组比如pat1中,(\d)为一组,(\d-\d)为一组。groups()以元组形式返回所有组的匹配字符串。不在括号内的值虽然参与匹配,但是通过group、groups获得不了,使用match[0]可以获得整个匹配的字符串,如上例match[0]返回“0731-8”,“73”是被不在括号中的。*匹配上的。

end()和start()返回索引位置,可以通过切片去获取原字符串的内容。

和str相似内容

re有一些和字符串相似的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#split()
text = """Ross McFluff: 834.345.1254 155 Elm Street
Ronald Heathmore: 892.345.3428 436 Finley Avenue
Frank Burger: 925.541.7625 662 South Dogwood Way
Heather Albrecht: 548.326.4584 919 Park Place"""

entries = re.split("\n+", text)
lst = [re.split(r":? ", entry, 3) for entry in entries]
print(lst)

#replace() | sub()
def dashrepl(matchobj):
if matchobj.group(0) == '-': return ' '
else: return '-'
re.sub('-{1,2}', dashrepl, 'pro----gram-files')
>>>'pro--gram files'
re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
>>>'Baked Beans & Spam'

split和字符串的用法一样,传入一个分隔符,返回一个被分隔符划分后的列表。不同之处在于,re的分隔符可以传入正则式,能够更加灵活地分割字符串。

sub()则是 re 形式的 str.replace() 它同样是令字符替代变得更加灵活。replace不可以传入正则表达式,而sub()可以,sub还可以在替代字符字段中传入callback函数。它的count字段,可以控制字符串替代的次数,超出次数后,剩下的字符串将不予替换。

sub()的第一个例子中,dashrepl传参matchobj。matchobj类型是re.Match obj,所以说sub()每成功匹配一次,便将这个对象传入dashrepl()处理,这里的.group(0)是当次re.Match obj 的group(0)。

暂时就这么多啦!