正则表达式
- 1.正则表达式常用操作符
- 2.正则表达式常用匹配规则
- 3.Re库主要功能函数
- 3.1 match()
- 3.1.1匹配目标(group(1))
- 3.1.2通用匹配(.*)
- 3.1.3贪婪与非贪婪
- 3.2 search()
- 3.3 findall()
- 3.4 sub()
- 3.5 compile
正则表达式是处理字符串的强大工具,可以对字符串进行检索、替换、匹配验证。通俗来说,正则表达式是一个模板,他要去匹配其他字符串是否符合条件,或者把符合条件的字符串找出来。对于爬虫来说,有了它,就可以从HTML中提取出我们想要的信息了。
1.正则表达式常用操作符
正则表达式的常用操作符(1)
操作符 | 说明 |
. | 表示任何单个字符 |
[ ] | 字符集,对单个字符给出取值范围 |
[^ ] | 非字符集,对单个字符给出排除范围 |
* | 前一个字符0次或无限次拓展 |
+ | 前一个字符1次或无限次拓展 |
? | 前一个字符0次或1次拓展 |
I | 左右表达式任意一个 |
实例:
[abc]表示a、b、c,[a-z]表示a到z单个字符;
[^abc]表示非a或b或c的单个字符串;
abc*表示ab、abc、abcc、abccc等;
abc+表示abc、abcc、abccc等;
abc?表示ab、abc;
abc|def表示abc、def
正则表达式的常用操作符(2)
操作符 | 说明 |
{m} | 拓展前一个字符m次 |
{m,n} | 拓展前一个字符m至n次(含n) |
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
( ) | 分组标记,内部只能用I操作符 |
\d | 数字,等价于[ 0-9 ] |
\w | 单词字符,等价于[ A-Za-z0-9 ] |
实例:
ab{2}c表示abbc;
ab{1,2}c表示abc、abbc;
^abc表示abc且在字符串开头;
$abc表示abc且在字符串结尾;
(abc)表示abc,(abc|def)表示abc、def;
正则表达式可以包含一些可选标志修饰符来控制匹配的模式,修饰符被指定为一个可选的标志。多个标志可以通过OR(|)来指定,如re.I|re.M被设置成I和M标志。
2.正则表达式常用匹配规则
常用匹配规则
修饰符 | 描述 |
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响^和$ |
re.S | 使.匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响\w,\W,\b,\B |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
其实正则表达式不是Python独有的,它也可以用在其他编程语言中。Python的re库提供了整个正则表达式的实现,利用这个库,可以在Python中使用正则表达式。re库有许多功能函数,可以解决正则表达式的匹配问题。
3.Re库主要功能函数
Re库主要功能函数
函数 | 说明 |
re.search() | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 |
re.match() | 从字符串的开始位置起匹配正则表达式,返回match对象 |
re.findall() | 搜索字符串,以列表类型返回全部能匹配的子串 |
re.split() | 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型 |
re.finditer | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象 |
re.sub() | 在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串 |
3.1 match()
先介绍第一个匹配方法match(),re.match(pattern, string)第一个参数传入正则表达式,第二个参数传入要匹配的字符串,就可以检测这个正则表达式是否匹配字符串。match()方法从字符串起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配就返回Nnon。示例如下:
import re
content = 'Hello 123 4567 World_This is a test'
print(content)
result = re.match('^Hello\s\d{3}\s\d{4}\s\w{10}', content)
print(result)
print(result.group())
print(result.span())
运行结果如下:
35
<re.Match object; span=(0, 25), match='Hello 123 4567 World_This'>
Hello 123 4567 World_This
(0, 25)
我们首先声明了一个字符串,‘Hello 123 4567 World_This is a test’,包含字母、空格、数字、下划线。接下来又声明了一个正则表达式:
'^Hello\s\d{3}\s\d{4}\s\w{10}'
用它来匹配字符串,^是匹配字符串的开头,就是以Hello为开头;然后\s匹配空白字符,匹配目标字符串中的空格;\d匹配数字,{3}代表匹配前面的规则三次,也就是匹配目标字符串中的123;最后\w{10}匹配10个字母及下划线。
打印输出结果,可以看到结果是 re.Match object,证明匹配成功。该对象有两个方法:group()方法可以输出匹配到的内容,结果是 Hello 123 4567 World_This,这就是按照正则表达式规则所匹配到的字符串中的内容;span()方法可以输出匹配的范围,结果是(0,25),这就是匹配到的结果字符串在原字符串中的位置。
3.1.1匹配目标(group(1))
可以使用()括号将想提取的字符串括起来。()实际标记了一个子表达式的开始和结束位置,被标记的子表达式会依次对应每一个分组,调用group()方法传入分组的索引即可获取提取的结果。
示例如下:
import re
content = 'Hello 1234567 World_This is a test'
result = re.match('^Hello\s(\d+)\sWorld', content)
print(result)
print(result.group())
print(result.group(1))
输出结果:
<re.Match object; span=(0, 19), match='Hello 1234567 World'>
Hello 1234567 World
1234567
调用group()函数,输出完整的匹配结果;
调用group(1),输出第一个被()包围的匹配结果。
3.1.2通用匹配(.*)
万能匹配 .*
其中, . 可以匹配任意字符(除换行符),*代表匹配前面的字符无限次,它们组合在一起就可以匹配任意字符了。
3.1.3贪婪与非贪婪
贪婪匹配:.*
非贪婪匹配:.?*
在贪婪匹配条件下, .* 会匹配尽可能多的字符。
在非贪婪匹配条件下,.*?匹配尽可能少的字符。
示例如下:
import re
content = 'Hello 1234567 World_This is a test'
result1 = re.match('^He.*(\d+).*test$', content)
result2 = re.match('^He.*?(\d+).*test$', content)
print(result1)
print(result1.group(1))
print(result2)
print(result2.group(1))
输出结果如下:
<re.Match object; span=(0, 34), match='Hello 1234567 World_This is a test'>
7
<re.Match object; span=(0, 34), match='Hello 1234567 World_This is a test'>
1234567
从结果看,由于 .后面是\d+,也就是至少一个数字,因此.匹配了尽可能多的字符,这里把 “llo 123456” 匹配了,给\d+留下了7;而.?匹配到Hello后面的空白字符时,再往后的字符就是数字了,\d+刚好能匹配,那么.?就不继续匹配了。所以.*?匹配了尽可能少的字符“llo ”,给\d+留下了1234567。
3.2 search()
在匹配时,search()方法依次扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容,如果没找到就返回None。
示例如下:
import re
print(re.search("ABC","CBA"))
print(re.search("ABC", "BCDABCD"))
print(re.search("ABC","AABCAABBCCABCD"))
输出结果:
None
<re.Match object; span=(3, 6), match='ABC'>
<re.Match object; span=(1, 4), match='ABC'>
3.3 findall()
用findall()方法进行匹配时,搜索整个字符串,然后以列表类型返回匹配正则表达式的所有内容。
示例如下:
import re
print(re.findall("a","AbbaCaD"))#前面字符串是规则(正则表达式),后面字符串是被校验的内容
print(re.findall("[A-Z]","ABCDeAbc"))
print(re.findall("[A-Z]+","ABCDeAbc"))
运行结果:
['a', 'a']
['A', 'B', 'C', 'D', 'A']
['ABCD', 'A']
3.4 sub()
可以使用正则表达式来修改文本。re.sub(pattern, repl, string),第一个参数传入正则表达式,第二个参数传入要替换成的字符串,第三个参数是原字符串。也就是在原字符串中找到pattern,把pattern换成repl。
示例如下:
import re
print(re.sub("a","A","AaBbCcAAA"))
运行结果:
AABbCcAAA
3.5 compile
compile()方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用。
示例如下:
import re
pattern = re.compile("AA") #正则表达式为AA
m = pattern.search("CBA")
print(m)
print(re.search(pattern, "ABCAABBCC"))
运行结果:
None
<re.Match object; span=(3, 5), match='AA'>
!建议在正则表达式中,被比较的字符串前面加上r,不用担心转义字符的问题
比如:
print("\aabd-\'" )#\a和\'被当做转义字符
print(r"\aabd-\'")
结果:
abd-'
\aabd-\'