Python专门内置了re
模块,用于实现正则表达式的操作。在这里我对该模块知识点做一个简单的总结,方便学习和查询。
1 模块导入
import re
doc = "@AAABCDBEDBFDEF 1234561_abcdef$@AA"
2 常用的正则符号
2.1 一般符号
符号 | 说明 | 示例 | 示例结果 |
---|---|---|---|
. | 匹配任意单个字符(不包括换行符\n) | re.findall('a.c', doc) | ['abc'] |
\ | 转义字符 | re.findall("f\$", doc) | ['f$'] |
[...] | 字符集。对应字符集中的任意字符 | re.findall('B[CFE]D', doc) | ['BCD', 'BED', 'BFD'] |
2.2 预定义字符集
符号 | 说明 | 示例 | 示例结果 |
---|---|---|---|
\d | 匹配一个数字字符,等价于[0-9] | re.findall('1\d', doc) | ['12'] |
\D | 匹配一个非数字字符,等价于[^0-9] | re.findall('1\D', doc) | ['1_'] |
\s | 匹配任何空白字符,包括空格、制表符、换行符等,等价于[\f\n\r\t\v] | re.findall('F\s1', doc) | ['F 1'] |
\S | 匹配任何非空白字符,等价于[^\f\n\r\t\v] | re.findall('1\S3', doc) | ['123'] |
\w | 匹配包括下划线的任何单词字符,等价于[A-Za-z0-9] | re.findall('1\wa', doc) | ['1_a'] |
\W | 匹配任何非单词字符,等价于[^A-Za-z0-9] | re.findall('\WA', doc) | ['@A'] |
2.3 数量词
符号 | 说明 | 示例 | 示例结果 |
---|---|---|---|
* | 匹配前一个字符0或无限次 | re.findall('BE*', doc) | ['B', 'BE', 'B'] |
+ | 匹配前一个字符1或无限次 | re.findall('BE+', doc) | ['BE'] |
? | 匹配前一个字符0或1次 | re.findall('BE?', doc) | ['B', 'BE', 'B'] |
{m} | 匹配前一个字符m次 | re.findall('@A{3}', doc) | ['@AAA'] |
{m,n} | 匹配前一个字符m至n次 | re.findall('@A{1,3}', doc) | ['@AAA', '@AA'] |
2.4 边界匹配
符号 | 说明 | 示例 | 示例结果 |
---|---|---|---|
^ | 匹配字符串开头 | re.findall('^@\D?', doc) | ['@A'] |
$ | 匹配字符串结尾 | re.findall('AA$', doc) | ['AA'] |
\A | 仅匹配字符串开头 | re.findall('\A@AA', doc) | ['@AA'] |
\Z | 仅匹配字符串结尾\Z | re.findall('@AA\Z', doc) | ['@AA'] |
3 常用匹配方法
3.1 search()
该方法匹配并提取第一个符合规律的内容,返回一个正则表达式对象。
import re
doc = "@AAABCDBEDBFDEF 1234561_abcdef@AA"
a = re.search("AA", doc)
print(a)
# <re.Match object; span=(1, 3), match='AAA'>
3.2 findall()
该方法匹配所有符合规律的内容,并以列表的形式返回结果。
import re
doc = "@AAABCDBEDBFDEF 1234561_abcdef@AA"
a = re.findall("AA", doc)
print(a)
# ['AA', 'AA']
3.3 fullmatch()
该方法检测整个字符串是否匹配,匹配失败返回None
,匹配成功返回一个正则表达式对象。
import re
doc = "abcdef"
a = re.fullmatch("abc", doc)
print(a)
# None
a = re.fullmatch("a\D*", doc)
print(a)
# <re.Match object; span=(0, 6), match='abcdef'>
4 模块修饰符
re模块包含一些可选的标志修饰符,用来控制匹配的模式,如下:
符号 | 说明 |
---|---|
re.I | 使匹配对大小写不敏感(注意这里的I是大写的i) |
re.L | 做本地化识别(local-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使匹配包括换行符在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响\w,\W,\b,\B |
re.X | 该标志通过给予更灵活的格式,以便将正则表达式写得更易理解 |
import re
doc = """abcdefAbC
xyz"""
a = re.findall("abc\w*", doc)
print(a)
# ['abcdefAbC']
a = re.findall("abc", doc, re.I)
print(a)
# ['abc', 'AbC']
a = re.findall("a(.*?)z", doc)
print(a)
# []
a = re.findall("a(.*?)z", doc, re.S)
print(a)
# ['bcdefAbC\n\n xy']
5 爬虫re模块使用技巧
5.1 非贪心算法(.*?)
上面的例子里有用到(.*?)
表达式,“()”
表示括号的内容作为返回结果,“.*?”
是非贪心算法,匹配任意的字符。例如,字符串"xxIxxddsgxxlovexxghhfgxxPythonxxsfsd",可以通过'xx(.*?)xx'匹配符合这种规则的字符串。
import re
a = "xxIxxddsgxxlovexxghhfgxxPythonxxsfsd"
info = re.findall('xx(.*?)xx', a)
print(info)
# ['I', 'love', 'Python']
5.2 跨行匹配re.S
在爬虫中,re.S是最常用的修饰符,它能够换行匹配。举个例子:
例如提取<div>指数</div>中的文字,可以通过以下代码实现:
import re
a = '<div>指数</div>'
word = re.findall('<div>(.*?)</div>', a)
print(word)
# [指数]
但是如果字符串是下面这样的多行字符串就会匹配不到字符串。
import re
a = '''<div>指数
</div>'''
word = re.findall('<div>(.*?)</div>', a)
print(word)
# []
这是因为findall()函数是逐行匹配的,当第1行没有匹配到数据时,就会从第2行开始重新匹配,这样就没法匹配到div标签中的文字信息,这时便可通过re.S来进行跨行匹配。
import re
a = '''<div>指数
</div>'''
word = re.findall('<div>(.*?)</div>', a, re.S)
print(word)
#['指数\n\n']