Python 爬虫十六式 - 第七式:正则的艺术

RE:用匹配来演绎编程的艺术

学习一时爽,一直学习一直爽python

  Hello,你们好,我是 Connor,一个个从无到有的技术小白。上一次咱们说到了 pyquery 今天咱们将迎来咱们数据匹配部分的最后一位重量级人物,也是编程语言中普及率最高的一个东西,它就是正则。正则长期以来占据着编程新手的禁忌之地,你们对它是又爱又恨。今天,咱们将揭开他神秘的面纱,直面正则,并助你征服它,让它成为你的得力助手!正则表达式

1. 正则的介绍

  因为正则并非 Python 所独有的内容,本文大部分会以正则的角度来进行描述和讲解,而不局限于 re 库,文章会穿插以 re 为例,对正则的例子进行讲解。算法

1.1 正则的起源

  想要完全掌握正则,就要从头至尾的了解它。那么正则是如何诞生的呢?这要追溯到上世纪人们对人类神经系统如何工做的早期研究。两位神经生理学家研究出一种数学方式来描述这些神经网络。具体叫什么我就不说了。编程

  1956 年, 一位数学家在上面两位神经生理学家早期工做的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,所以采用“正则表达式”这个术语。缓存

  随后他们发现能够将这一研究成果普遍的应用于其它领域的研究。Ken Thompson 使用它来进行一些早期的计算搜索算法的一些研究,Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。网络

  而后,正则表达式在各类计算机语言或各类应用领域获得了广大的应用和发展,演变成为目前计算机技术森林中的一只形神美丽且声音动听的百灵鸟。到目前正则表达式在基于文本的编辑器和搜索工具中依然占据这一个很是重要的地位。编程语言

  在最近的六十年中,正则表达式逐渐从模糊而深奥的数学概念,发展成为在计算机各种工具和软件包应用中的主要功能。不只仅众多UNIX工具支持正则表达式,近二十年来,在 Windows 的阵营下,正则表达式的思想和应用在大部分 Windows 开发者工具包中获得支持和嵌入应用!编辑器

  Windows 系列产品对正则表达式的支持发展到无与伦比的高度,目前几乎全部 Microsoft 开发者和全部.NET语言均可以使用正则表达式。包括 Python、Java、JavaScript、Go 等非 Windows 系列的产品也对正则进行了支持,这无疑将正则变成了编程界的宠儿,能够说得正则者得天下!函数

  因此,看到这里是否是想要火烧眉毛地来学会正则了???让咱们一块儿来看看正则的概念:工具


1.2 正则的概念

  正则表达式是对字符串操做的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

  Emmn… 看了这么官方的描述仍是有些懵逼,说白了正则表达式就是经过一些指定好的特殊字符来代替某种字符。举个例子:你们小时候都玩过扑克游戏排火车,就是当你如今排的牌和前面的任意一张大小相同的时候,不管中间有多少,有什么牌你均可以获取这中间全部的牌。正则和这个相似,无视中间全部的东西,只要知足你这个规则,就能够取出中间全部的内容!

  不知道个人例子够不够清晰,反正我绞尽脑汁也只想到了这一个比较像的例子,若是你有什么更好的例子,能够留言或评论,我将引用你的例子。

  说完了正则的概念,咱们再来看看正则有哪些特色吧!


1.3 正则的特色

  正则表达式有以下的特色:

  1. 灵活性、逻辑性和功能性很是的强;
  2. 能够迅速地用极简单的方式达到字符串的复杂控制。
  3. 适用于任何字符串

2. 正则表达式的基础知识

  这里日后都是基础的东西,若是你以为你都懂了想直接看Python的re库请 点击这里>>

  既然大概了解了正则的历史以及他的功能和特色,那么让咱们从正则表达式的基础知识来开始学习吧。大多数教程都是从元字符开始的,可是他们忽略了一些最基础的东西,这些东西对于初级运用或许没有任何关系,可是当你要使用到高级用法的时候极可能会形成混乱,甚至是遗忘,因此咱们在开始前先来讲一说正则的基础知识:

2.1 字符串的位置讲解

  在咱们的印象中,光标的位置就是在字符以后的,可是实际上在底层,光标指的并非当前字符的位置,而是光标前面的这个位置,如图:

  真实的光标位置指的是光标以前的这个字母,是这个字母 e 的位置,因此在一个长度为 n 的字符串中,总共有 n + 1 个位置。例如:

(0)a(1)b(2)c(3)
复制代码

在这个长度为 3 的字符串 abc 中,一共有 (0)(1)(2)(3)四个位置


2.2 占有字符和零宽度

  可能如今说占有字符和零宽度会让你感受有些不知所措,可是当你看完后面的内以后再反过来看占有字符和零宽度的时候你就会恍然大悟,将这两个概念了然于心了。

  正则表达式匹配过程当中,若是子表达式匹配到东西,而并不是是一个位置,并最终保存到匹配的结果当中。这样的就称为占有字符,而只匹配一个位置,或者是匹配的内容并不保存到匹配结果中,这种就称做零宽度,占有字符是互斥的,零宽度是非互斥的。也就是一个字符,同一时间只能由一个子表达式匹配,而一个位置,却能够同时由多个零宽度的子表达式匹配。


2.3 正则表达式的控制权与传动

  正则表达式由左到右依次进行匹配,一般状况下是由一个表达式取得控制权,从字符串的的某个位置进行匹配,一个子表达式开始尝试匹配的位置,是从前一个匹配成功的结束位置开始的。


3. 正则表达式的语法

3.1 正则表达式的元字符

  正则表达式的元字符是正则表达式的根本,全部的正则表达式都有元字符组成,正则表达式的元字符包括下列几种:

3.1.1 基本元字符

字符 描述
. 匹配除换行符外的任意字符
* 匹配0个或多个符合表达式的字符
? 匹配0个或1个符合表达式的字符
+ 匹配1个或多个符合表达式的字符
[...] 匹配方括号内的任意字符
[^...] 匹配除方括号字符内的任意字符

3.1.2 转义元字符

字符 描述
\ 用于转义下一个字符
\A 仅匹配字符串的开头
\b 匹配一个单词的边界
\B 匹配非单词边界
\cX 匹配指明的控制字符
\d 匹配一个数字,等价于[0-9]
\D 匹配一个非数字,等价于[^0-9]
\f 匹配一个换页符,等价于\x0c和\cL
\n 匹配一个换行符,等价于\x0a和\cJ
\t 匹配一个制表符,等价于\x09和\cI
\r 匹配一个回车符,等价于\x0d和\cM
\s 匹配 一个不可见的字符
\S 匹配一个可见的字符
\v 匹配一个垂直制表符,等价于\x0b和\cK
\w 匹配包括下划线的任何单词字符
\W 匹配任何非单词字符
\Z 仅匹配字符串的末尾
\xn 匹配转移为\xn的十六进制转义字符
\un 匹配一个Unicode转义字符

3.1.3 限定类元字符

字符 描述
{n} 匹配肯定的n个字符
{n,} 匹配至少n个字符
{n,m} 匹配至少n个字符,至多m个字符
| 或符号,用于链接多个表达式
- 范围符,只能用于方括号中,如[a-z]
^ 匹配字符串的开头,在方括号中表示取反
$ 匹配字符串的末尾
(parameter) 将括号内的内容进行匹配并分组
(?!parameter) 正向否认预查,匹配不是parameter的内容
(?=parameter) 正向确定预查,匹配是parameter的内容
(?:parameter) 匹配parameter获取匹配结果
(?<=parameter) 反向确定预查,在任何匹配的paraemter处开始匹配字符串
(?<!parameter) 反向否认预查,在任何不符合parameter的地方开始匹配字符串

  只是在这里向你罗列元字符你是不会懂如何使用正则的,请稍安勿躁,稍后咱们将以 Python 中的正则为例,为你们逐一展现各类元字符的用法。若是你比较急切,请点击这里来快速查看 re 库的使用方法。了解了元字符,咱们再来认识一下可打印字符与非打印字符:


3.2 打印字符与非打印字符

3.2.1 打印字符

  如你所见,你在网上浏览到的全部的字符,这包括全部大写和小写字母、全部数字、全部标点符号和一些其余符号。这些所有可见的字符都叫作可打印字符

3.2.2 非打印字符

  非打印字符也能够是正则表达式的组成部分。下表列出了表示非打印字符的转义序列:

字符 描述
\cx 匹配由x指明的控制字符。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^\f\n\r\t\v ]
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

  打印字符和非打印字符很是易懂,没什么难点,一笔带过,下面咱们来看看运算符的优先级:


3.3 正则表达式运算符的优先级

  正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式很是相似。相同优先级的从左到右进行运算,不一样优先级的运算先高后低。下表从最高到最低说明了各类正则表达式运算符的优先级顺序:

运算符 描述
\ 转义符
(), (?:), (?=), [] 圆括号和方括号
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, \任何元字符、任何字符 定位点和序列(即:位置和顺序)
| 替换,"或"操做字符

  运算优先级很是相似于四则运算,没什么好说的,下面咱们来看看正则的匹配模式:


3.4 正则的匹配模式(表达式修饰符)

  正则表达式有时候不仅是须要使用简单的正则语句,有时候还须要挑选合适的匹配模式(表达式修饰符),经过这些不一样的匹配模式,能够提高匹配的效率。正则的匹配模式如表:

模式 描述
/a 强制从字符串头开头进行匹配
/i 不区分大小写匹配
/g 全局匹配
/m 多行匹配
/s 特殊字符匹配
/u 不重复匹配
/x 忽略模式中的空白

  到这里就介绍完元字符了,若是你想直接看元字符的使用示例,请 点击这里>>

4. Python 的正则库 -- re库

  正则被广大编程语言所支持,Python也不例外,Python 官方为咱们封装了 re 库来支持正则的使用,下面咱们一块儿来走进 Python 的 正则库--re库:

4.1 Python 中的正则匹配模式

  Python 的正则也是正则,因此它也有匹配模式。但这匹配模式又有些不一样于正则的表达方式,咱们来看一看:

修饰符 描述
re.A 强制从字符串头开始匹配
re.I 使匹配对大小写不敏感
re.L 作本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的全部字符
re.U 根据Unicode字符集解析字符
re.X 该标志经过给予你更灵活的格式以便你将正则表达式写得更易于理解。

  能够看到,匹配模式并再也不是 /* 来进行表示了,而是变成了 re.* 来进行表示了。


4.2 Python 中的正则经常使用方法

   Python 既然是一种语言,那么它定然不会让咱们傻敷敷的去使用,Python 为咱们封装好了方法,咱们来逐一看一下都有哪些方法吧:

4.2.1 compile()

re.compile(pattern, flags=0)
复制代码

  这个方法用来将正则表达式进行编译,返回一个Pattern对象。这么说你必定仍是很懵逼,咱们来举个例子:

import re
string = "Learning makes a good man better and ill man worse."
pattern = re.compile(r"m\w+")
result = pattern.findall(string)
print(result)
复制代码

返回结果:

['makes', 'man', 'man']
复制代码

  这样就显而易见了,先将正则表达式进行编译,在下次使用的时候直接给编译好的正则表达式一个字符串让它去匹配就行了。这样作的好处是提升了性能,若是你要处理大文档,建议你这样使用。

4.2.2 escape()

escape(pattern)
复制代码

  这个方法能够用来匹配除 ASCII字符,数字和特殊字符 ‘_’ 之外的全部字符。官方的说法就是不同,这个东西有时候真的挺让人懵逼的,简单来讲,这个方法就是用来消除字符串中的任何特殊字符效果的。

  我举个例子你就明白了。有时候问哦们在匹配网址的时候,由于 ‘.’ 是特殊字符,因此有些时候咱们没法成功的进行匹配,咱们须要转义后再进行匹配,大部分人的操做是这样的:

import re
string = "www.baidu.com"
result = re.findall(r"baidu\.com", string)
print(result)
复制代码

  这样作确实能够达到咱们想要的效果,可是对于想要玩骚操做的咱们来讲,这样太 Low 了,因此就有了这样的方式:

import re
string = "www.biadu.com"
result = re.findall(re.escape("baidu.com"), string)
print(result)
复制代码

  这样一来,咱们就省去了写转义的麻烦步骤,案例中须要转移的内容较少,可能看不出有什么优点,可是当你匹配大量须要转移的内容的时候,这样作不只能够省去打转义字符的麻烦,并且也防止咱们漏打,错打转义字符。

  固然,你也要注意一点,使用这个方法会消除一切特殊字符的特殊效果,使用这种方法匹配具备必定的局限性,不能再进行模糊匹配了,请按需使用。

4.2.3 findall()

findall(pattern,string,flags = 0复制代码

  经过这个方法匹配出来的是字符串中全部非重叠匹配的列表。老规矩,举个例子:

import re
string = "Learning makes a good man better and ill man worse."
result = re.findall(r'm\w+', string)
print(result)
复制代码

运行结果:

['makes', 'man', 'man']
复制代码

  

4.2.4 finditer()

finditer(pattern, string, flags=0)
复制代码

  经过这个方法能够将字符串中全部非重叠匹配上返回迭代器。对于每一个匹配,迭代器返回一个匹配对象,匹配结果中包含有空对象。

  简单的说,就是返回一个可迭代的 Objct 对象,这是它和 findall() 方法惟一的区别。 咱们举个例子:

import re
string = """ QQ邮箱: 123456789@qq.com 网易邮箱: 123456789@163.com 126邮箱: 123456789@126.com"""
ls = re.finditer(r"(\d+@\w+.com)", string, re.S)
print(type(ls))
for item in ls:
    print(item.group())
复制代码

运行结果以下:

<class 'callable_iterator'>
123456789@qq.com
123456789@163.com
123456789@126.com
复制代码

  生成的可迭代的 Object 对象中,内部对象都为 SRE_Match 对象,该对象不可直接提取匹配的内容,须要经过 group() 方法来进行提取。

4.2.5 fullmatch()

fullmatch(pattern, string, flags=0)
复制代码

  经过这个方法能够用来判断整个字符串是否匹配规则,若是符合规则则返回 match object。不符合则返回 None。举个例子:

import re
string = """QQ邮箱: 123456789@qq.com"""
ls = re.fullmatch(r"QQ邮箱: 123456789@qq.com", string, re.S)
print(ls.group())
复制代码

运行结果以下:

QQ邮箱:  123456789@qq.com
复制代码

若是咱们随意改变一下规则:

import re
string = """QQ邮箱: 123456789@qq.com"""
ls = re.fullmatch(r"QQ邮箱", string, re.S)
print(ls)
复制代码

运行结果:

None
复制代码

  能够看得出,只有当整个字符串都符合匹配规则的时候才能匹配到东西,不然的话返回的是 None

4.2.6 match()

match(pattern, string, flags=0)
复制代码

  使用这个方法能够尝试在字符串的开头进行匹配,返回匹配对象,若是未找到匹配,则返回None。

  你应该注意到了,它是在字符串的开头进行匹配的,若是你仍是不太清楚,那咱们接着来看例子:

import re
string = """QQ邮箱:123456789@qq.com"""
ls = re.match(r"QQ邮箱", string, re.S)
print(ls)
复制代码

运行结果以下:

<_sre.SRE_Match object; span=(0, 4), match='QQ邮箱'>
复制代码

由于咱们匹配的法则在开头有,若是咱们换个规则的话:

import re
string = """QQ邮箱:123456789@qq.com"""
ls = re.match(r"\d+", string, re.S)
print(ls)
复制代码

运行结果:

None
复制代码

  按照咱们的想法它应该会匹配到@前面的一串数字吧?可是实际上它并无匹配到。这就是所谓的在字符串的开头进行匹配。

4.2.7 purge()

  经过这个方法能够清除正则表达式的缓存。这个方法貌似没有啥好说的 …

4.2.8 search()

search(pattern, string, flags=0)
复制代码

  搜索整个字符串以匹配符合规则的字符串,若是有则返回匹配对象,若是没有则返回None。前面说的 match() 方法是只在头部进行匹配,而 search() 方法能够在字符串中的任意位置进行匹配。例如:

import re
string = """QQ邮箱:123456789@qq.com"""
ls = re.search(r"\d+", string, re.S)
print(ls)
复制代码

运行结果以下:

<_sre.SRE_Match object; span=(5, 14), match='123456789'>
复制代码

  能够看的出,没有在字符串首部的字符也被匹配出来了。相比 match() 方法,search() 方法,findall() 方法要用的更多些。

4.2.9 split()

split(pattern,string,maxsplit = 0,flags = 0复制代码

  看到这个方法我想你们第一时间想到的是字符串中的 split() 方法,恭喜你,猜对了,这个方法和 字符串中自带的 split() 方法大同小异,这个方法增长的功能是能够经过正则表达式来进行分割。例如:

首先举一个都能理解的功能:

import re
string = """abc,123456789,@qq.com"""
ls = re.split(r",", string)
print(ls)
复制代码

运行结果:

['abc', '123456789', '@qq.com']
复制代码

  能够看得出,如今的分割方法和 字符串中自带的 split() 方法没有什么区别。下面咱们再看多出来的用法:

import re
string = """abc123456789@qq.com"""
ls = re.split(r"\d+", string)
print(ls)
复制代码

运行结果:

['abc', '@qq.com']
复制代码

  能够看得出,该方法将 数字做为分割依据进行了分割。若是你足够细心的话,你会发现这个方法还有一个参数,叫 maxsplit 这个方法表明着最大分割次数。好比:

import re
string = """abc,123456789,@qq.com"""
ls = re.split(r",", string, 1)
print(ls)
复制代码

运行结果以下:

['abc', '123456789,@qq.com']
复制代码

  能够看到它只进行了一次分割,maxsplit 就是用来控制分割次数的,分割从左到右依次进行分割。分割 maxsplit 次。

4.2.10 sub()

sub(pattern,repl,string,count = 0,flags = 0复制代码

  将全部符合规则的字符串替换成 repl。最多替换 count个,默认所有替换。这是我我的认为正则中除了 findall() 方法外最有用的方法了。批量替换超级有用!!!

  咳咳,激动了啊,下面咱们来讲说这个方法的使用:

import re
string = """abc123456789@qq.com"""
ls = re.sub(r"456", "abc", string)
print(ls)
复制代码

运行结果以下:

abc123abc789@qq.com
复制代码

  一下就把字符串中的 456 给替换成 abc了,贼带劲。用了这个方法你还想用 replace方法吗?那个方法多傻,若是你不以为,一会我会让你认同个人观点的。咱们先往下说,sub() 方法也有一个计数参数 count,咱们能够经过给它赋值来指定替换个数。好比:

import re
string = """abc12abc67abc@qq.com"""
ls = re.sub(r"abc", "---", string, 2)
print(ls)
复制代码

运行结果:

---12---67abc@qq.com
复制代码

  在上面的程序中咱们指定了替换个数2,因此结果中只替换了两个 abc,并无所有替换。若是不指定 count 参数的话,默认会进行所有替换。

4.2.11 subn()

subn(pattern,repl,string,count = 0,flags = 0复制代码

  这个方法和 sub() 方法没有什么本质上的区别,惟一的不一样就是它返回的是一个元组,这个元组包含有两个内容,(1)替换后的字符串,(2)整个字符串中的替换次数。举个例子:

import re
string = """abc12abc67abc@qq.com"""
ls = re.subn(r"abc", "---", string)
print(ls)
复制代码

运行结果以下:

('---12---67---@qq.com', 3)
复制代码

4.2.12 template()

template(pattern, flags=0)
复制代码

  这个方法我查了不少资料,国内的网站并无几我的写这个方法的,可能有写的,可是没有用这个标题来进行发表吧,总之我没有找到什么详细的资料,可是经过他的官方解释:“编译模板模式,返回模式对象” 能够看得出它返回的是一个模式对象,和 re.compile() 方法相似,返回的都是一个模式对象。应该用法和 re.complie()类似。

  可是我查阅了国外的网站,你们有提到说发现这个函数,可是并无发现有什么用处。你们说,可能这个函数并未实现预期想要的功能,或者这个函数出现了什么问题而关闭了。因此只能暂时停留在这个状态。固然平时咱们也用不到这个函数

  我经过本身的琢磨,本身的尝试,发现这个函数大部分函数功能是和 compile() 方法相同的。好比:

import re
abc = re.template(r"abc", re.I)
string = "abcasdfadsfABCasdfabcasdfasdf"
result = abc.findall(string)
print(result)
复制代码

运行结果以下:

['abc', 'ABC', 'abc']
复制代码

可是最主要的问题是,该方法禁用全部的特殊字符,即re的元字符,好比:

import re
abc = re.template(r"\d+", re.I)
string = "abcasdfadsfABCasdfabcasdfasdf"
result = abc.findall(string)
print(result)
复制代码

运行结果以下:

Traceback (most recent call last):
File "G:/Python/PyWin/test.py", line 2, in <module>
    abc = re.template(r"\d+", re.I)
    ....
复制代码

这个状况下就直接报错了。因此我想不出来这个函数有什么做用。之因此写出来就当给你们开眼了。若是真的须要使用模板的话,仍是建议你们使用 re.compile() 方法来进行操做。

好了,这就是 Python 正则库 re 中的全部函数了。下面我还有几个内容要给你们说


4.3 re 中的 Pattern 对象

   这个Pattern 我为何不在讲方法以前说呢,就是怕大家不明白,让我一会儿给弄晕了,因此我选择在讲完全部方法以后再说。这样的话有些人不须要了解这么深,直接找到他们想要的方法,直接去使用就行了。这样也方便他们使用…

  好好,咱们如今来讲 **Pattern **对象。那什么是 Pattern 对象呢?若是你仔细看以前我写的方法的话,你会发现几乎每一个正则的方法里都有一个 Pattern 参数 ,回想一下那个参数写的什么? 对,Pattern对象就是咱们编译后的正则规则。

  以前咱们在讲 re.compile() 方法的时候说过,这个方法返回的就是一个 Pattern对象。这个对象几乎能够执行 re 中的全部方法。是比较简单的一个对象。相信你们均可以理解。我以为也没啥好说的了。


re 中的 Match 对象

  Emmn….说完了 Pattern对象咱们如今来讲说 Match 对象。

  好的好的,我必定好好说这个….这个Match 对象呢,是 re构建的一个对象。咱们经过 match()fullmatch()search()fjinditer(),这几种方法返回的都是 Match 对象。咱们来看看一个 Match 对象中都包含什么:

<_sre.SRE_Match object; span=(3, 6), match='abc'>
复制代码
  • span 指的是匹配到的字符串在字符串中的位置。例中的 3,6 分别是开始位置和结束位置。
  • match 指的是匹配到的内容

下面咱们来讲说 Match 对象中经常使用的方法:

方法 解释
end([group]) 获取组的结束位置
expand(string) 将match对象中的字符串替换成指定字符串
group(index) 某个组匹配的结果
groupdict() 返回组名做为key,每一个分组的匹配结果做为value的字典
groups() 全部分组的匹配结果,每一个分组组成的结果以列表返回
start([group]) 获取组的开始位置
span([group]) 获取组的开始和结束位置

  这就是 Match 对象的全部内容了。仍是很容易掌握的嘛。


5. 正则表达式全部元字符的示例

  讲完了正则表达式了,也讲完了python中的 re库,下面咱们来将以前说好的元字符的示例逐一展现出来:

5.1 基本元字符的示例

字符 描述
. 匹配除换行符外的任意字符
* 匹配0个或多个符合表达式的字符
? 匹配0个或1个符合表达式的字符
+ 匹配1个或多个符合表达式的字符
[...] 匹配方括号内的任意字符
[^...] 匹配除方括号字符内的任意字符

元字符 “.” 的示例:

import re
string = "abcdefghigklmnopqrstuvwxyz1234567890"
result = re.match(r".bc", string)
print(result.group())

运行结果:
abc
复制代码

元字符 “*” 的示例:

import re
string = "abcdefghigklmnopqrstuvwxyz1234567890"
result = re.search(r"(a.*g)", string)
print(result.group())

运行结果:
abcdefg
复制代码

元字符 “?” 的示例:

import re
string = "aaabcdefg"
result = re.search(r"a?b", string)
print(result.group())

运行结果:
ab
复制代码

元字符 “+” 的示例:

import re
string = "aaabcdefg"
result = re.search(r"a+", string)
print(result.group())

运行结果:
aaa
复制代码

元字符 “[…]” 的示例:

import re
string = "aaabcdefg123456789"
result = re.findall(r"[\D]+", string)
print(result)

运行结果:
['aaabcdefg']
复制代码

元字符 “[^...]” 的示例:

import re
string = "aaabcdefg123456789"
result = re.findall(r"[^\d]+", string)
print(result)

运行结果:
['aaabcdefg']
复制代码

5.2 转义元字符的示例

字符 描述
\ 用于转义下一个字符
\A 仅匹配字符串的开头
\b 匹配一个单词的边界
\B 匹配非单词边界
\cX 匹配指明的控制字符
\d 匹配一个数字,等价于[0-9]
\D 匹配一个非数字,等价于0-9
\f 匹配一个换页符,等价于\x0c和\cL
\n 匹配一个换行符,等价于\x0a和\cJ
\t 匹配一个制表符,等价于\x09和\cI
\r 匹配一个回车符,等价于\x0d和\cM
\s 匹配 一个不可见的字符
\S 匹配一个可见的字符
\v 匹配一个垂直制表符,等价于\x0b和\cK
\w 匹配包括下划线的任何单词字符
\W 匹配任何非单词字符
\Z 仅匹配字符串的末尾
\xn 匹配转移为\xn的十六进制转义字符
\un 匹配一个Unicode转义字符

元字符 “\” 的示例:

import re
string = "aaabcdefg123456789"
result = re.findall(r"\d+", string)
print(result)

运行结果:
['123456789']
复制代码

元字符 “\A” 的示例

import re
string = "aaabcdefg123456789"
result = re.findall(r"\A\w", string)
print(result)

运行结果:
['a']
复制代码

元字符 “\b” 的示例

import re
string = "aaabcdefg123456789"
result = re.findall(r"\b\w{5}", string)
print(result)

运行结果:
['aaabc']
复制代码

元字符 “\B” 的示例

import re
string = "I'm the king of the world"
result = re.findall(r"\B\w+", string)
print(result)

运行结果:
['he', 'ing', 'f', 'he', 'orld']
复制代码

元字符 “\d” 的示例

import re
string = "abcdefg1234567"
result = re.findall(r"\d+", string, re.S)
print(result)

运行结果:
['1234567']
复制代码

元字符 “\D” 的示例

import re
string = "abcdefg1234567"
result = re.findall(r"\D+", string, re.S)
print(result)

运行结果:
['abcdefg']
复制代码

元字符 “\f” 的示例

import re
string = "abcdefg\f1234567"
result = re.findall(r"\f", string, re.S)
print(result)

运行结果:
['\x0c']
复制代码

元字符 “\n” 的示例

import re
string = "abcdefg\n1234567"
result = re.findall(r"\n\d+", string, re.S)
print(result)

运行结果:
['\n1234567']
复制代码

元字符 “\t” 的示例

import re
string = "abcdefg\t1234567"
result = re.findall(r"\t", string, re.S)
print(result)

运行结果:
['\t']
复制代码

元字符 “\r” 的示例

import re
string = """abcdefg\r1234567"""
print(string)
result = re.findall(r"\r", string, re.S)
print(result)

运行结果:
1234567
['\r']
复制代码

元字符 “\s” 的示例

import re
string = """abcdefg\n1234567"""
result = re.findall(r"\s", string, re.S)
print(result)

运行结果:
['\n']
复制代码

元字符 “\S” 的示例

import re
string = """abcdefg\n1234567"""
result = re.findall(r"\S+", string, re.S)
print(result)

运行结果:
['abcdefg', '1234567']
复制代码

元字符 “\w” 的示例

import re
string = """I_m the king of the world"""
result = re.findall(r"\w+", string, re.S)
print(result)

运行结果:
['I_m', 'the', 'king', 'of', 'the', 'world']
复制代码

元字符 “\W” 的示例

import re
string = """I'm the king of the world"""
result = re.findall(r"\W+", string, re.S)
print(result)

运行结果:
["'", ' ', ' ', ' ', ' ', ' ']
复制代码

元字符 “\Z” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\w{2}\Z", string, re.S)
print(result)

运行结果:
['yz']
复制代码

元字符 “\xn” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\x77", string, re.S)
print(result)

运行结果:
['w']
复制代码

元字符 “\un” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\u0077", string, re.S)
print(result)

运行结果:
['w']
复制代码

5.3 限定类元字符的示例

字符 描述
{n} 匹配肯定的n个字符
{n,} 匹配至少n个字符
{n,m} 匹配至少n个字符,至多m个字符
| 或符号,用于链接多个表达式
- 范围符,只能用于方括号中,如[a-z]
^ 匹配字符串的开头,在方括号中表示取反
$ 匹配字符串的末尾
(parameter) 将括号内的内容进行匹配并分组
(?!parameter) 正向否认预查,匹配不是parameter的内容
(?=parameter) 正向确定预查,匹配是parameter的内容
(?:parameter) 匹配parameter获取匹配结果
(?<=parameter) 反向确定预查,在任何匹配的paraemter处开始匹配字符串
(?<!parameter) 反向否认预查,在任何不符合parameter的地方开始匹配字符串

元字符 “{n}” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w{2}", string, re.S)
print(result)

运行结果:
['uvw']
复制代码

元字符 “{n,}” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w{3,}", string, re.S)
print(result)

运行结果:
['uvwxyz']
复制代码

元字符 “{n,m}” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w{1,3}", string, re.S)
print(result)

运行结果:
['uvwx']
复制代码

元字符 “|” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w|x\w", string, re.S)
print(result)

运行结果:
['uv', 'xy']
复制代码

元字符 “-” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"[a-z]+", string, re.S)
print(result)

运行结果:
['uvwxyz']
复制代码

元字符 “^” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"[^1-9]+", string, re.S)
print(result)

运行结果:
['uvwxyz']
复制代码

元字符 “$” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\w{3}$", string, re.S)
print(result)

运行结果:
['xyz']
复制代码

元字符 “(parameter)” 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u(\w{2})x(\w{2})", string, re.S)
print(result)

运行结果:
[('vw', 'yz')]
复制代码

元字符 “(?=parameter)” 的示例

import re
string = """COD4 COD6 COD8"""
result = re.findall(r"COD.(?=4)", string, re.S) #匹配.=4的字符串COD
print(result)

运行结果:
['COD4']
复制代码

元字符 “(?!parameter)” 的示例

import re
string = """COD4 COD6 COD8 """
result = re.findall(r"COD.(?!4)", string, re.S) # 匹配 .!=4的字符串
print(result)

运行结果:
['COD6', 'COD8']
复制代码

元字符 “(?:parameter)” 的示例

import re
string = """COD4COD6COD8"""
result = re.findall(r".*?(?:4)", string, re.S) # 匹配获取参数为4的字符串
print(result)

运行结果:
['COD4']
复制代码

元字符 “(?<=parameter)” 的示例

import re
string = """COD4 COD6 COD8 """
result = re.findall(r"COD.(?<=4)", string, re.S) # 从右向左匹配.=4的字符串
print(result)

运行结果:
['COD4']
复制代码

元字符 “(?<!parameter)” 的示例

import re
string = """COD4 COD6 COD8 """
result = re.findall(r"COD.(?<!4)", string, re.S) # 从右向左匹配.!=4的字符串
print(result)

运行结果:
['COD6', 'COD8']
复制代码

  到这里咱们就把正则的全部元字符的示例就都演示完了。我所演示的是最基础的用法,若是真的想要使用高级的用法,仍是要本身多进行尝试,多练习。练习的多了使用正则才会信手拈来。


下期预告

  你看你说了这么多,又是访问网页,又是获取数据的,说了半天咱们仍是不知道怎么用。我会只是单独的给大家说这么简单吗?固然会有练习的啦。敬请期待下一期:Python 爬虫十六式 - 第八式:实例解析-全书网!咱们经过全书网来让你一下吸取前面的知识。

  好了,这就是今天的内容了,不知道你又学会了多少呢?我是Connor,一个从无到有的技术小白,愿你在前进的道路上坚持不懈!

学习一时爽,一直学习一直爽!

系列文章

Python 爬虫十六式 - 第一式:HTTP协议 >>>
Python 爬虫十六式 - 第二式:urllib 与 urllib3 >>>
Python 爬虫十六式 - 第三式:Requests的用法 >>>
Python 爬虫十六式 - 第四式: 使用Xpath提取网页内容 >>>
Python 爬虫十六式 - 第五式:BeautifulSoup,美味的汤 >>>
Python 爬虫十六式 - 第六式:JQuery的假兄弟-pyquery >>>
Python 爬虫十六式 - 第八式:实例解析-全书网 >>>

相关文章
相关标签/搜索