python3爬虫-3.正则表达式与re库

常用表达式

字符 描述
\d 代表任意数字,就是阿拉伯数字 0-9 这些玩意。
\D 大写的就是和小写的唱反调,\d 你代表的是任意数字是吧?那么我 \D 就代表不是数字的。
\w 代表字母,数字,下划线。也就是 a-z、A-Z、0-9、_。
\W 跟 \w 唱反调,代表不是字母,不是数字,不是下划线的。
\n 代表一个换行。
\r 代表一个回车。
\f 代表换页。
\t 代表一个 Tab 。
\s 代表所有的空白字符,也就是上面这个:\n、\r、\t、\f。
\S 跟 \s 唱反调,代表所有不是空白的字符。
\A 代表字符串的开始。
\Z 代表字符串的结束。
^ 匹配字符串开始的位置。
$ 匹配字符串结束的位置。
. 代表所有的单个字符,除了 \n \r
[...] 代表在 [] 范围内的字符,比如 [a-z] 就代表 a到z的字母
[^...] 跟 [...] 唱反调,代表不在 [] 范围内的字符
{n} 匹配在 {n} 前面的东西,比如: o{2} 不能匹配 Bob 中的 o ,但是能匹配 food 中的两个o。
{n,m} 匹配在 {n,m} 前面的东西,比如:o{1,3} 将匹配“fooooood”中的前三个o。
{n,} 匹配在 {n,} 前面的东西,比如:o{2,} 不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。
* 和 {0,} 一个样,匹配 * 前面的 0 次或多次。 比如 zo* 能匹配“z”、“zo”以及“zoo”。
+ 和{1,} 一个样,匹配 + 前面 1 次或多次。 比如 zo+能匹配“zo”以及“zoo”,但不能匹配“z”。
和{0,1} 一个样,匹配 ?前面 0 次或 1 次。
`a b`
() 匹配括号里面的内容。

知道了这些之后,我们怎么用 python 来进行判断呢?

那就要使用到 python 的库了re

re库

re.match

使用这个方法,主要传入两个参数

  • 第一个就是我们的匹配规则

  • 第二个就是需要被过滤的内容

例如,我们想要从

Xiaoshuaib has 100 bananas

拿到一个数字,那么我们就可以这样

import re

content = 'Xiaoshuaib has 100 bananas'
res = re.match('^Xi.*(\d+)\s.*s$',content)
print(res.group(1))

通过刚刚说的匹配符号 可以定义出相应的匹配规则

在这里我们将我们需要的目标内容用 () 括起来

此刻我们获得结果是

0

那么如果我们想要 100 这个数字呢?可以这样

import re

content = 'Xiaoshuaib has 100 bananas'
res = re.match('^Xi.*?(\d+)\s.*s$',content)
print(res.group(1))

看出区别了么 第二段代码我们多了一个 ?符号

在这里呢 涉及到两个概念

一个是贪婪匹配 另一个是非贪婪匹配

所谓贪婪匹配 就是我们的第一段代码 一个数一个数都要去匹配

而非贪婪呢我们是直接把 100 给匹配出来了

re.S

刚刚我们用到的.*?是我们在匹配过程中最常使用到的 表示的就是匹配任意字符

但是.*?.代表所有的单个字符,除了 \n \r

如果我们的字符串有换行了 怎么办呢?比如这样

content = """Xiaoshuaib has 100 
bananas"""

那么我们就需要用到 re 的匹配模式了

说来也简单 直接用 re.S 就可以了

import re

content = """Xiaoshuaib has 100 
bananas"""
res = re.match('^Xi.*?(\d+)\s.*s$',content,re.S)
print(res.group(1))

re.search

可能有些朋友会觉得 匹配一个东西还要写开头结尾 有点麻烦

那么就可以使用 re 的另一个方法了:re.search

它会直接去扫描字符串 然后把匹配成功的第一个结果的返回给你

import re

content = """Xiaoshuaib has 100 
bananas"""
res = re.search('Xi.*?(\d+)\s.*s',content,re.S)
print(res.group(1))

这样子也是可以获取 100 的

re.findall

但是如果我们的内容是这样的

content = """Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;"""

想要获取所有的 100 呢?

这时候就要用到 re 的另一个方法了

通过它我们就能轻松的获取所有匹配的内容了

import re

content = """Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;"""
res = re.findall('Xi.*?(\d+)\s.*?s;',content,re.S)
print(res)

这里的结果是

['100', '100', '100', '100']

re.sub

又有朋友觉得 如果我们想直接替换匹配的内容呢

就比如刚刚的字符串 可不可以把 100 直接替换成 250 呢?

那就要用到 re 的另一个方法了:re.sub可以这样

import re

content = """Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;
Xiaoshuaib has 100 bananas;"""
content = re.sub('\d+','250',content)
print(content)

那么结果就变成了

Xiaoshuaib has 250 bananas;

Xiaoshuaib has 250 bananas;

Xiaoshuaib has 250 bananas;

Xiaoshuaib has 250 bananas;

再来说说 re 的另一个常用到的方法吧

re.compile

这个主要就是把我们的匹配符封装一下

import re

content = "Xiaoshuaib has 100 bananas"
pattern = re.compile('Xi.*?(\d+)\s.*s',re.S)
res = re.match(pattern,content)

print(res.group(1))

其实和我们之前写的一样的

res = re.match('^Xi.*?(\d+)\s.*s$',content,re.S)

只不过 compile 一下 便于以后复用

关于 re 模块和正则表达式就介绍完啦

wistbean/learn_python3_spider: python爬虫教程系列

posted @ 2021-08-23 09:12  1ink  阅读(109)  评论(0编辑  收藏  举报