第059讲(论一只爬虫的自我修养7:正则表达式3)

今天我们先接着上节课的内容,把 Python3 正则表达式特殊符号及用法(详细列表)这个表格讲完:
上节课我们介绍了正则表达式的特殊字符中的元字符,正则表达式的特殊字符除了 元字符之外呢,还有 一种就是通过反斜杠加上一个普通字符组成的特殊符号。我们接下来谈谈它们的含义。
\序号,这个我们上节课已经讲过了,序号就是数字:
①引用序号对应的子组所匹配的字符串,此时序号的范围是 1~99,子组的序号是从 1 开始计算。
②如果序号是以 0 开头,或者 3 位数字的长度。那么不会被用于引用对应的子组,而是用于匹配八进制数字所表示的ASCII 码值对应的字符。
这在上节课已经讲过了,我们接下来就讲上节课没有讲过的:

\A :这个符号在默认情况下和 托字符(^)是一样的,都是匹配输入字符串的开始位置。也就是 说,要是前面是 \A 或者 ^ 符号,那么这个字符就必须出现在字符串的开头,才能算是匹配。 有不懂的,可以查看上节课 托字符(^)的讲解。\Z:这个符号在默认情况下和 美元符号($)是一样的,都表示匹配输入字符串的结束位置。

我们上面两条都说的是 默认情况下,但不是说完全一样的。因为正则表达式还有一个 编译标志的设置,如果说你设置了一个 re.MULTILINE 标志,那么托字符(^)也匹配换行符之后的位置,同时,美元符号($)也匹配换行符之前的位置。
但是呢,无论你设不设置这个标志,这个 \A 和 \Z 都只能匹配字符串的 开头 和 结束 位置。
像这种匹配位置的字符,我们给它们一个名字,叫做 临框断言,言外之意就是它们不会匹配任何字符,它们只用于定位一个位置。
\b 也是一个临框断言,它是匹配一个单词的边界,单词被定义为 Unidcode 的字母数字或下横线字符。举个例子:
>>> import re >>> re.findall(r"\bFishC\b", "FishC.com!FishC_com!(FishC)") ['FishC', 'FishC']

上面只找到了两个 FishC,你知道它哪一个FishC没有找到吗?(事实上是 FishC_com 中的FishC),因为下划线也被认为是单词字符,不是边界。点号(.)感叹号(!)、括号都被认为是单词边界。
接下来是 \B,其实就是与 \b 相反,匹配非单词边界。
举个例子:py\B 会匹配字符串 “python”、“py3” 或 “py2”,但不会匹配 "py "、“py.” 或 “py!”
\d:① 对于 Unicode(str 类型)模式:匹配任何一个数字,包括 [0-9] 和其他数字字符;如果开启了 re.ASCII 标志,就只匹配 [0-9]。
② 对于 8 位(bytes 类型)模式:匹配 [0-9] 中任何一个数字。
\D:与 \d 相反,匹配任何非 Unicode 的数字;如果开启了 re.ASCII 标志,则相当于匹配 [^0-9]。
\s :①对于 Unicode(str 类型)模式:匹配 Unicode 中的空白字符(包括 [ \t\n\r\f\v] 以及其他空白字符);如果开启了 re.ASCII 标志,就只匹配 [ \t\n\r\f\v]
② 对于 8 位(bytes 类型)模式:匹配 ASCII 中定义的空白字符,即 [ \t\n\r\f\v]
\w:① 对于 Unicode(str 类型)模式:匹配任何 Unicode 的单词字符,基本上所有语言的字符都可以匹配,当然也包括数字和下横线;如果开启了 re.ASCII 标志,就只匹配 [a-zA-Z0-9_]
什么是单词字符?对于英文(就是ASCII)的话,像“Python”,P y t h o n 这6个字符都是单词字符,还有数字和下横线也是。如果是 Unicode 的话, Unicode 是全球化的语言,像中文,中文什么是单词字符?例如“我爱Python”,其中的 我 爱 这两个汉字也是单词字符。
② 对于 8 位(bytes 类型)模式:匹配 ASCII 中定义的字母数字,即 [a-zA-Z0-9_]
举个例子:
>>> re.findall(r"\w", "我爱Python3 (love_python.com!)") ['我', '爱', 'P', 'y', 't', 'h', 'o', 'n', '3', 'l', 'o', 'v', 'e', '_', 'p', 'y', 't', 'h', 'o', 'n', 'c', 'o', 'm']

除了 空格 括号 点号 感叹号,其它的汉字、字母、下横线、数字 都是单词字符。
\W :其实就是与 \w 相反, 匹配任何非 Unicode 的单词字符,;如果开启了 re.ASCII 标志,则相当于 [^a-zA-Z0-9_]
最后,正则表达式还支持大部分 Python 字符串的转义符号:\a,\b,\f,\n,\r,\t,\u,\U,\v,\x,\
注1:\b 通常用于匹配一个单词边界,只有在字符类中才表示“退格”
注2:\u 和 \U 只有在 Unicode 模式下才会被识别
注3:八进制转义(\数字)是有限制的,如果第一个数字是 0,或者如果有 3 个八进制数字,那么就被认为是八进制数;其他情况则被认为是子组引用;至于字符串,八进制转义总是最多只能是 3 个数字的长度。
Python3 正则表达式特殊符号及用法(详细列表)这个表格终于讲解完毕了,还是那句话,别死记硬背,查用就行。
接下来讲解下一个内容:编译正则表达式: 什么情况下需要编译正则表达式?
如果你需要重复地使用某个正则表表达式,那么你可以先把该正则表达式编译成模式对象。
我们使用 re.compile() 方法来编译……
re.compile 函数 compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。 语法格式为: re.compile(pattern[, flags]) 参数:
  • pattern : 一个字符串形式的正则表达式
  • flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
1.re.I 忽略大小写
2.re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
3.re.M 多行模式
4.re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
5.re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
6.re.X 为了增加可读性,忽略空格和 # 后面的注释
关于这6个编译标志的详解可以查看 Python3 如何优雅地使用正则表达式(详解三)
>>> p = re.compile(r"[A-Z]") >>> type(p)

我们把正则表达式 [A-Z] 进行编译,赋值给 一个变量 p,这个变量 p 就是一个模式对象。
我们可以直接使用 p 进行 search() 方法 和 findall() 方法 的使用:
>>> p.search("I love Python") <_sre.SRE_Match object; span=(0, 1), match='I'> >>> p.findall("I love Python") ['I', 'P']

有些朋友可能会问,你是使用模块级别的方法效率比较高,还是说使用编译后的方法效率比较高,其实这个没有一定的定论,因为两种的优化差不多。这里,如果你至少需要使用一次正则表达式,你直接使用模块级别的方法就可以了,但是呢,如果你下面要多次使用这个正则表达式,你就可以先对其进行编译,再使用,这样更方便。我们以方便为主,既然学习Python,就不要多考虑效率的问题了,能优化的,Python的设计者都已经优化得差不多了。
接下来我们来谈谈这个 编译标志。
我们在 Python3 如何优雅地使用正则表达式(详解三)里有仔细的给大家列举出来。
接下来我们来谈谈这个 编译标志。
我们在 Python3 如何优雅地使用正则表达式(详解三)里有仔细的给大家列举出来。
编译标志让你可以修改正则表达式的工作方式。在 re 模块下,编译标志均有两个名字:完整名和简写。
我们需要提一点的是 VERBOSE(简写 X)这个标志,使用 re.VERBOSE(或者 re.X)在某些时候能给我们带来很多好处。
【第059讲(论一只爬虫的自我修养7:正则表达式3)】因为呢,稍微一个中等复杂度的正则表达式,你就会把它写成人模狗样,非常非常的复杂,为什么呢?因为我们上节课已经说过了,正则表达式里 你不能随便加空格,因为空格它会被认为是其中的一个匹配元素,你不能加空格,不能加 Tab 键,不能 使用三重引号 换行,所以呢,你写出来的东西就会看起来很难理解。但是如果你开启了 VERBOSE,它就是支持 空格,支持Tab键,支持换行,也支持注释的。

    推荐阅读