正则表达式是一种模板表达式语言
通过定义 规则 去 匹配、查找、替换、分割 一个长字符串中特定的子字符信息。
如在一篇文章中查找出所有合法的电子邮箱地址,则可以先用正则表达式定义一个电子邮箱规则,然后再使用这个规则在整个字符串中查找。
爬虫程序一般都会借助正则表达式定义的规则在爬出来的内容中做 精细化筛检 。
正则表达式有自己独立于其它计算机语言的语法结构,且大部分计算机编程语言都提供有对正则表达式的支持。如 Java、JavaScript、python……
普通字符匹配规则
普通字符指 字母、数字、汉字、下划线、以及没有特殊定义的标点符号。 正则表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。
如需在 “ This is my love ” 中匹配 “ love ” 子字符串,则表达式就是 " love "。
转义符匹配规则
在正则表达式语法中有很多字符除了其自身意义外,还有语法赋予的特殊意义。如:^、$、?、*……
如在 This is my lo$ve 中匹配出 lo$ve ,则表达式不能写成 lo$ve 。默认情况下,正则表达式的语法解析器不会把 $ 其视为其自身含义,而是把它解析成特定的含义( 边界定义 )。所以表达式中需使用转义符 \ 进行转义。需写成 lo$ve
另,有些无法输入的字符也需要通过转义符进行转义:
\n | 代表换行符 |
---|---|
\t | 制表符 |
\ | 代表* * 本身 |
^ , $,. , ( , ) , { ,** } , ? , + , * , | , [ ,** ] | 匹配这些字符本身 |
标准字符集
如果需要在一个字符串中匹配一些具有共同特征的字符,则可以使用字符集规则,如在一个 Firse 1,Second 2,Three 3…… 字符串中匹配所有数字或所有空格。
\d | 任意一个数字,****0~9 中的任意一个 |
---|---|
\w | 任意一个字母或数字或下划线,也就是 A Z,a z,0~9,_ 中任意一个 |
\s | 包括空格、制表符、换行符等空白字符的其中任意一个 |
. | 小数点可以匹配任意一个字符 |
Tip:标准字符集是区分大小写的
大小写都能描述特定的字符群体,互为相反关系。如 \d 指任意数字,\D 指除了数字之外的其它字符。
自定义字符集合
用户可以定义自己的字符集合,用来满足开发时的特定需要,如在 123456789ABaCbDEcdFG 中查找或匹配奇数和小写字母。
自定义集合使用 [ ] 来定义。
[ab5@] | 匹配 "a" 或 "b" 或 "5" 或 "@" |
---|---|
[^ abc] | 匹配 a,b,c 之外的任意一个字符 |
[f-k] | 匹配 "f"~"k" 之间的任意一个字母 |
[^A-F0-3] | 匹配 "A" "F","0" "3" 之外的任意一个字符 |
正则表达式中的特殊符号,如果被包含于中括号中,则失去特殊意义,但 \ [ ] : ^ - 除外。
比如:[\d.-+],将可以匹配数字,小数点和 + - 符号。( 小数点和 + 号失去语法赋予的意义 )
修饰匹配次数的特殊符号
{n} | **表达式重复 n次 ** |
---|---|
{m,n} | 表达式至少重复 m 次,最多重复 n 次 |
{m,} | 表达式至少重复 m 次 |
? | 匹配表达式 0 次或者 1 次,相当于 {0,1} |
+ | 表达式至少出现 1 次,相当于 {1,} |
* | 表达式不出现或出现任意次,相当于 {0,}** |
正则表达式的语法相对而言较简单,可以在使用过程中查阅相关文档
Python 提供有正则表达式模块,使用时只需要导入即可。
import re
re 模块中提供了几个常用方法
方法原型说明:
import re re.match(pattern, string, flags=0)
Tip: 从字符串起始位置匹配 ,如果从起始位置匹配不了,就返回 none。
案例一:
import re m = re.match('www', 'www.baidu.com') print ("结果: ", m) print ("起始与终点:", m.span()) print ("起始位置:", m.start()) print ("终点位置:", m.end())
输出结果:
结果:起始与终点: (0, 3) 起始位置: 0 终点位置: 3
案例二:
import re line = "You are just the person I want to see" m = re.match(r'(.*) are (.*?) the', line) print ("结果:", m) # groups() 返回匹配的字符列表 for res in m.groups(): print(res) print("匹配上的完整子字符串",m.group(0)) # 和 groups() 中的结果一致 print("第一个匹配上的字符:",m.group(1)) print("第一个匹配上的字符:",m.group(2))
原型说明:
import re re.search(pattern, string, flags=0)
Tip:re.search 方法的参数语义和 re.match 方法相同
re.match 方法只能从字符串的起始位置进行匹配 ,re.search扫描整个字符串并返回第一个成功的匹配。其它的性质则是一样的。
案例:
import re m_match = re.match('baidu', 'www.baidu.com') m_search = re.search('baidu', 'www.baidu.com') print ("re.match 输出结果:",m_match) print ("re.search 输出结果:",m_search)
输出结果
re.match 输出结果: None re.search 输出结果:
原型说明
import re re.findall(pattern, string, flags=0)
Tip :re.findall 方法的参数说明和 re.search 相同
案例:
import re #返回 Match 类型 re_match = re.match('[0-9]+', '12345 is the first number, 23456 is the sencond') #返回 Match 类型 re_search = re.search('[0-9]+', 'The first number is 12345, 23456is the sencond') # #返回列表类型 re_findall = re.findall('[0-9]+', '12345 is the first number,23456 is the sencond') print ("re.match:",re_match.group()) print ("re_search",re_search.group()) print ("re_findall:",re_findall)
输出结果:
re.match: 12345 re_search 12345 re_findall: ['12345', '23456']
方法原型说明:
import re re.sub(pattern, repl, string, count=0, flags=0)
import re p=r'\d+' text="AB12CD34EF56HK" replace_text=re.sub(p,' ',text) print("默认替换所有:",replace_text) replace_text=re.sub(p,' ',text,count=1) print("仅替换一次:",replace_text) replace_text=re.sub(p,' ',text,count=2) print("仅替换二次:",replace_text)
输出结果:
默认替换所有: AB CD EF HK 仅替换一次: AB CD34EF56HK 仅替换二次: AB CD EF56HK
方法原型说明:
import re re.split(pattern, string, maxsplit=0, flags=0)
案例:
import re p = r'\d+' text = 'AB12CD34EF56GH' lst = re.split(p, text) print("默认对整个字符串进行分割:", lst) lst = re.split(p, text, maxsplit=1) print("仅分割一次:", lst) lst = re.split(p, text, maxsplit=2) print("分割二次:", lst)
输出结果
默认对整个字符串进行分割: ['AB', 'CD', 'EF', 'GH'] 仅分割一次: ['AB', 'CD34EF56GH'] 分割二次: ['AB', 'CD', 'EF56GH']
python 提供的 re 模块中有很多方法可借助正则表达式方便、快捷地完成字符串的相关操作,对于爬虫程序来讲正则表达式是其不可忽视的一部分。