Python3网络爬虫——(5)正则表达式(re模块)
一、正则表达式
1、正则表达式是字符串搜索引擎
Python正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
2、正则表达式在线测试工具:http://tool.oschina.net/regex
3、常见匹配模式:
4、正则表达式修饰符 - 可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
二、Python语言中的re模块拥有全部的正则表达式功能
1、re.match函数
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
函数语法:
re.match(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式 |
匹配成功re.match方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
(1)最常规的匹配
import re
content='Hello 123 4567 World_This is a Regex Demo'
result=re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content)
print(len(content))
print(result)
print(result.group()) #输出匹配的整个表达式字符串
print(result.span()) #输出匹配结果的范围
(2)泛匹配
import re
content='Hello 123 4567 World_This is a Regex Demo'
result=re.match('^Hello.*Demo$',content)
print(result.group()) #输出匹配的整个表达式字符串
结果为:Hello 123 4567 World_This is a Regex Demo
(3)匹配目标
import re
content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^Hello\s(\d+)\sWorld.*Demo$',content)
print(result.group()) #输出匹配的整个表达式字符串
print(result.group(1))#获取匹配目标(即小括号内的字符串)
(4)贪婪匹配
import re
content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^He.*(\d+).*Demo$',content)# .*匹配尽可能多的字符
print(result.group()) #输出匹配的整个表达式字符串
print(result.group(1))#获取匹配目标(即小括号内的字符串)
(5)非贪婪匹配
import re
content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^He.*?(\d+).*Demo$',content)# .*?匹配尽可能少的字符
print(result.group()) #输出匹配的整个表达式字符串
print(result.group(1))#获取匹配目标(即小括号内的字符串)
(6)匹配模式
import re
content='Hello 1234567 World_This ' \
'is a Regex Demo'
result=re.match('^He.*?(\d+).*?Demo$',content,re.S) #re.S匹配换行符
print(result.group()) #输出匹配的整个表达式字符串
print(result.group(1))#获取匹配目标(即小括号内的字符串)
(7)转义
import re
content='price is $5.00'
result=re.match('price is \$5\.00',content) #特殊字符用转义
print(result.group()) #price is $5.00
总结:
尽量使用泛匹配、使用括号得到匹配目标、尽量使用非贪婪模式,有换行符就用re.S
2、re.search函数
re.search 扫描整个字符串并返回第一个成功的匹配。
函数语法:
re.search(pattern, string, flags=0)
函数参数说明:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
匹配成功re.search方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 | 描述 |
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
例子:
import re
content='Extra strings Hello 1234567 World_This is a Regex Demo Extra strings'
result=re.search('Hello.*?(\d+).*?Demo',content)
print(result)
print(result.group(1))
总结:为匹配方便,能用search就不用match
注:re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配
3、re.findall函数
re.findall搜索字符串,在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配一次 findall 匹配所有。
语法格式为:
findall(string[, pos[, endpos]])
参数:
- string : 待匹配的字符串。
- pos : 可选参数,指定字符串的起始位置,默认为 0。
- endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
例1:
例2(拿到所有的歌名信息):
4、re.sub函数
re.sub 替换字符串中每一个匹配的子串后返回替换后的字符串。
语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
import re
content='Extra strings Hello 1234567 World_This is a Regex Demo Extra strings'
content1=re.sub('\d+','',content)
print(content1)
content2=re.sub('\d+','Replacement',content)
print(content2) #r 表示字符串为非转义的原始字符串
content3=re.sub('(\d+)',r'\1 8910',content) # \1是把第一个括号里的内容拿过来
print(content3)
结果:
5、re.compile函数
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
语法格式为:
re.compile(pattern[, flags])
参数:
- pattern : 一个字符串形式的正则表达式
import re
content='Hello 1234567 World_This ' \
'is a Regex Demo'
pattern=re.compile('Hello.*Demo',re.S)
result=re.match(pattern,content)
print(result)
6、re.finditer函数
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)
参数:
参数 | 描述 |
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等 |
import re
content='12a32bc43jf3'
it=re.finditer(r'\d+',content)
for mat in it:
print(mat.group())
7、re.split函数
re.split(pattern, string[, maxsplit])按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割。
import re
content='one1two2three3four4'
result=re.split(r'\d+',content)
print(result) #['one', 'two', 'three', 'four', '']
实战练习:爬取豆瓣图书相关信息
爬取结果: