【Python 爬虫基础】正则表达式

正则表达式

计算机科学领域有个笑话:“如果你有一个问题打算用正则表达式来解决,那么就是两个问题了。”

然而,正则表达式(通常简写 regex)经常被嘲笑是一堆随机符号混杂在一起,看起来毫无意义。这种印象让人们对其避而远之,然后费尽心思写一堆复杂的查找和过滤函数,其实他们真正需要的就是一行正则表达式。

其实正则表达式上手一点也不难,而且运行很快,通过一些简单的例子就可以轻松地学会。

尝试正则表达式

之所以叫正则表达式,是因为它们可以识别正则字符串(regular string);也就是说,它们可以这么定义:“如果你给我的字符串符合规则,我就返回它”,或者是“如果字符串不符合规则,我就忽略它”。这在快速浏览大文档,以查找像电话号码和邮箱地址之类的字符串时,是非常方便的。

注意这里我用了一个词组正则字符串。什么是正则字符串?其实就是任意可以用一系列线性规则构成的字符串,就像:

  1. 字母“a”至少出现一次;
  2. 后面跟着字母“b”,重复五次;
  3. 后面再跟字母“c”,重复任意偶数次;
  4. 最后一位是字母“d”或“e”。

满足上面规则的字符串有“aaaabbbbbccccd”“aabbbbbcce”等。

正则表达式就是表达这种规则的一种快捷方式。这组规则的正则表达式如下所示:

aa*bbbbb(cc)*(d|e)

乍一看这个字符串会觉得有点奇葩,但是当我们把它分解之后就会很清楚了。

aa*
  • a 后面跟着 a*(读作 a 星)表示“重复任意次 a,包括 0 次”。这样就可以保证字母 a 至少出现一次。
bbbbb
  • 这没什么特别的,就是 5 个 b。
(cc)*
  • 任意偶数个字符都可以编组,这个规则是用括号括住两个 c,然后后面跟一个星号,表示可以有任意次两个 c(也可以是 0 次)。
(d|e)
  • 在两个表达式中间加一个竖线(|)表示“这个或那个”。本例中表示“增加一个 d 或者一个 e”。这样就可以保证字符串的结尾是这两个字母之一。

常用的正则表达式的符号

下表列出了常用的正则表达式符号以及简短的解释和示例。这个列表中并没有囊括全部的正则表达式,不同语言中的正则表达式符号会略有不同。但是,这里列出的 12 个符号是 Python 中最常用的正则表达式符号,可以用于查找和获取几乎任意字符串类型。

符号含义例子匹配结果
*匹配前面的字符、子表达式或括号里的字符 0 次或多次a* b*aaaaaaaaaaa,aaabbbbbb,bbbbbbb
+匹配前面的字符、子表达式或括号里的字符至少 1 次a+b+aaaaaaaaab,aaabbbbb,abbbbb
[ ]匹配中括号里的任意一个字符(相当于“任选一个”)[A-Z]*APPLE,CAPITALS,QWERTY
()表达式编组(在正则表达式的规则里编组会优先运行)(a* b)*aaabaab,abaaab,ababaaab
{m,n}匹配前面的字符、子表达式或括号里的字符m到n次(包括m或n)a{2,3}b{2,3}aabbb,aaabbb,aabb
[ ^ ]匹配任意一个不在中括号里的字符[^A-Z]*apple,lowercase,qwerty
|匹配任意一个由竖线分隔的字符、子表达式(注意是竖线,不是大写字母I)b(a|i|e)dbad,bid,bed
.匹配任意单个字符(包括符号、数字和空格等)b.dbad,bzd,b$d,b d
^指字符串开始位置的字符或子表达式^aapple,asdf,a
\转义字符(把有特殊含义的字符转换成字面形式)\.\ |\\.|\
$经常用在正则表达式的末尾,表示“从字符串的末尾端匹配”。如果不用它,每个正则表达式实际都带着“.*”模式,只会从字符串开头进行匹配。这个符号可以看成是 ^ 符号的反义词。[A-Z]*[a-z] * $ABCabc,zzzyx,Bob
?!“不包括”。这个奇怪的组合通常放在字符或正则表达式的前面,表示字符不能出现在目标字符串。这个符号比较难用,毕竟字符通常会在字符串的不同部位出现。如果要在整个字符串中彻底排除某个字符,就加上 ^ 和 $ 符号^((?![A-Z]).)*$no-caps-here,a4ef!ne

正则表达式在实际中的一个经典应用是识别邮箱地址。虽然不同邮箱服务器的邮箱地址的具体规则不尽相同,但是我们还是可以创建几条通用规则。每条规则对应的正则表达式如下表所示:

规则正则表达式
1.邮箱地址的第一部分至少包括一种内容:大写字母、小写字母、数字 0-9 、点号(.)加号(+)或下划线(_)[A-Za-z0-9\ . _+]+:这个正则表达式简写非常智慧。例如,它用 “A-Z” 表示“A-Z中的任意大写字母”。把所有可能的序列和符号放在中括号(而不是小括号)里表示“可以是方括号中任何一个符号”。要注意后面的加号,它表示“这些符号都可以出现多次,但至少要出现一次”
2.之后,邮箱地址会包含一个@符号@:这个符号很简单:@符号必须出现在中间位置,并且只能出现一次
3.在符号@之后,邮箱地址还必须至少包含一个大写或小写字母[A-Za-z]+:可能只在域名的前半部分、符号@后面用字母。而且,至少要有一个字符
4.之后跟一个点号(.)\.:在域名之前必须有一个点号(.)。退格在这里用作转义字符
5.最后邮箱地址用 com、org、edu、net 结尾(实际上,顶级域名有很多种可能,这里作为示例只演示这四个就够用了)(com|org|edu|net):这样列出了后半部分邮箱地址中可能出现在点号之后的字母序列

把上面的规则连接起来,就获得了完整的正则表达式:

[A-Za-z0-9\._+]+@[A-Za-z]+\.(com|org|edu|net)

当动手开始写正则表达式的时候,最好先写一个步骤列表,具体描述出你的目标字符串结构。还要注意处理一些细节。比如,当你识别电话号码的时候,会考虑国家代码和分机号吗?

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QuantumStack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值