简介
正则表达式并不是python独有的,它就是一种表达式,适用于多种语言,但是我们目前博客以学python爬虫,所以从python爬虫角度分析及使用
概念
-
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
-
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
- 字符串是编程时涉及到的最多的一种数据结构,对字符串进行操作的需求几乎无处不在。比如判断一个字符串是否是合法的Email地址(123456789@qq.com),虽然可以编程提取@前后的子串,再分别判断是否是单词和域名,但这样做不但麻烦,而且代码难以复用。
-
-
正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。
-
正则表达式是对字符串操作的⼀种逻辑公式,就是⽤事先定义好的⼀些特定字 符、及这些特定字符的组合,组成⼀个“规则字符串”,这个“规则字符 串”⽤来表达对字符串的⼀种过滤逻辑
正则表达式的应⽤场景
- 表单验证(例如 : ⼿机号、邮箱、身份证… )
- 爬⾍
提取指定字符
获取数据结合,有用的数据只有一部分,我们可以指定字符串进行匹配
语法 | 含义 | 表达式 | 匹配的字符串 |
---|---|---|---|
一般字符串 | 匹配自身 | abc | abc |
. | 可以匹配除了换行符“\n”之外的任意字符 | a.c | abc、aec、a#c、a9c |
[] | 匹配括号中的任意字符 | a[1b$]c | a1c、abc、a$c |
[^] | "^"在中括号内,表示取反,即匹配出了中括号内的数据 | a[^123]c | abc、a4c |
\ | 转义字符,使最后一个字符改变原来的意思,如“\”中的"."代表本身,而不是任意字符 | a[db.\]c | adc、abc、a.c、a\c |
预定义字符集
语法 | 含义 | 表达式 | 匹配的字符串 |
---|---|---|---|
^ | 匹配字符串的开始 | ^abc | abcde |
$ | 匹配字符串的结尾 | abc$ | 123abc |
\b | 匹配单词的开始或结束 | \babc\b | abc |
\d | 匹配数字0~9 | a\dc | a3c |
\D | 匹配非数字,相当于[^\d] | a\Dc | a@c |
\s | 匹配任意空白字符,等价于[<空格>\tnlr\f]. | alsc | ac |
\S | 匹配任意非空白字符,等价于[^\s] | a\Sc | aDc、a*c |
\w | 匹配单词字符[A-Za-20-9_ ],字母、数字、下划线 | a\wc | abc、alc、aBc、a_c |
\W | 匹配非单词字符,等价于[^\w] | a\Wc | a%C、ac、a-C |
匹配数字相关的字符集
特殊场景使用匹配字符集
正则表达式常用方法
数量限定
语法 | 含义 | 表达式 | 匹配的字符串 |
---|---|---|---|
* | 匹配前一个字符0次或多次 | abc* | ab、abccc |
+ | 匹配前一个字符1次或多次 | abc+ | abc、abccc |
? | 匹配前一个字符0次或1次 | abc? | ab、abc |
{m} | 匹配前一个字符m次 | a{2}bc | aabc |
{m,} | 匹配前一个字符m次或更多次 | a{2,}bc | aabc、aaaabc |
{,m} | 匹配前一一个字符0-m次 | a{,2}bc | bc、abc、aabc |
{m,n} | 匹配前一个字符m至n次 | a{1,3}bc | abc、aabc、 aaabc |
分支匹配
如果有多种匹配规则,则满足任意一种规则即可完成匹配,这时就要用到分支条件的匹配。比如日体格式,20810-10 20181010 或者2018 10.10都满足条件,从左往右,匹配到任意一个即可
语法 | 含义 | 表达式 | 匹配的字符串 |
---|---|---|---|
| | 左右两个表达式满足一一个即可, 先左后右,一旦左边匹配成功,则跳过右边匹配 | \d{4}-ld{2}-\d{2}|\d{4}^d{2}^\d{2}|\d{4}\.\d{2}\.\d{2} | 2018-12-12 |
分组
上表中的正则表达式不仅能匹配到2018- 12-12这样的日期,也能匹配到2018-99-99这样不存在的日期,需要对月份日期做具体的限定,月份应该是0[1-9]1[0-2], 日应该是0[-9][12][0-9]3[01],完整表达式为\d{4}-(O[1-9]|1[0-2])-(O0[1-9][12][0-9]3[01])。这里没有判断每月是否有31日,二月是否为闰月,更详细的判断请读者练习完成。
每个“0”为一个分组,分组的起始编号为1,每遇到一一个“(”编号加1,在提取数据时,可以方便地将-组数据单独提取出来。
零宽断言
先介绍什么是零宽断言,在程序设计中,断言指的是判断一个情况是否为真,而在正则表达式中,零宽断言指的是当断言表达式为真的时候,再进行匹配,匹配的时候并不匹配断言表达式的内容。断言有不同的形式,结合如下字符串更好理解:
Rita repeatedwhat Reardonrecited when
(1)先行断言,也叫作零宽度正预测先行断言,表达式: (?=exp); 当断言表达式为真时,匹配断言表达式前面的位置。先行断言的执行步骤为:先从要匹配的字符串中的最右端找到第一个断言表达式,再匹配其前面的表达式;若无法匹配,则继续查找第二个断言表达式,再匹配第二个断言表达式前面的字符串;若能匹配,则匹配。例如\w+(?=ted),会匹配到repea和reci (断言表达是“ted”不会匹配),而.*(?=t)则 会匹配到My WeChat account。
(2)后发断言,也叫作零宽度正回顾后发断言,表达式: (?<=exp), 当断言表达式为真时,匹配断言表达式后面的位置。与先行断言执行顺序相反,先从要匹配的字符串中的最左端找到第1个断言表达式,再匹配其后面的表达式;若无法匹配,则继续查找第2个断言表达式,再匹配第2个断言表达式后面的字符串;若能匹配,则匹配。例如(?<=re)w+, 会匹配到peated和cited,而(?<=re).*则会匹配到peated what Reardon recited when。
(3)零宽度负预测先行断言,表达式(?!exp), 当断言表达式不成立时,匹配断言表达式前面的位置:若断言表达式成立,则不匹配。例如\b(?!R)w+匹配不以大写字母R开头的字符串。(4)零宽度负回顾后发断言,表达式(?<!exp),当断言表达式不成立时,匹配断言表达式后面的位置:若断言表达式成立,则不匹配。例如w+(?<!ed)b匹配不以ted结尾的字符串。
贪婪模式与非贪婪模式
正则表达式默认是贪婪模式,也就是尽可能多地匹配字符串,比如使用a\w+b匹配a123b123b时,得到的是a123b123b,而不是a123b。想匹配到a123b的时候,就需要启用非贪婪模式,将表达式改为a\w+?b就可以匹配到a123b。数量限定中启用非贪婪模式
语法 | 含义 |
---|---|
*? | 匹配前一个字符0次或多次,尽可能少重复 |
+? | 匹配前一个字符1次或多次,尽可能少重复 |
?? | 匹配前一个字符0次或1次,尽可能少重复 |
{m,}? | 匹配前一个字符m次或更多次,尽可能少重复 |
{m,n}? | 匹配前一个字符m至n次,尽可能少重复 |