Python爬虫之快速入门正则表达式
正则表达式
正则表达式(regular expression)简称(regex), 是一种处理字符串的强大工具。它作为一种字符串的匹配模式,用于查看指定字符串是否存在于被查找字符串中,替换指定字符串,或是通过匹配模式查找指定字符串。正则表达式在不同的语言里面,语法也基本是相同的,也就是说学会了一种语言的正则,再学习其它的就很快了。
其主要的匹配过程是:
先用正则语法定义一个规则(pattern)
然后用这个规则与你download的网页字符串进行对比,根据pattern提取你想要的数据。
好了,让我们看看Python正则表达式的语法:
我们举一个常遇到的一个例子。比如,一个人的邮箱是这样的lixiaomei@qq.com,那么我们如何从一大堆的字符串把它提取出来呢?
根据正则语法,我们可以这样来定义一个pattern:w+@w+.com
为什么这么定义呢?让我们来看看。
"w" 的意思是单词字符[A-Za-z0-9_]。注意是 "单字符串",可以是A-Z或者a-z或者0-9或者_各国语言中的任意一个。
"+" 匹配前一个字符1次或无限次。那么 "w+" 组合起来的意思就是匹配一次或无限多次的但字符串[A-Za-z0-9]组合的字符串。
"@" 是邮箱的特定字符,所以固定不变。
第二个 "w+" 与前一个是一个道理,匹配一次或无限次的[A-Za-z0-9]组合的字符串。
" . " 的含义是将" . "转义,因为 " . " 本身也是正则语法中的其中一种,为了真的得到 ".com" 而不是带有功能的" . ", 所以在前面加上 "" 转义字符。
所以,不论是例子中的 lixiaomei@qq.com,还是其它如xiaoxiao@126.com之类的邮箱,只要符合规则全都可以匹配,怎么样,简单吧!
问题来了,有的邮箱格式可是xiaoxiao@xxx.xxx.com这样的!这样的话上面的规则就不能用了。没错,上面的规则比较特殊,只能匹配单一格式的邮箱名。那么怎样设计一个满足以上两种格式的pattern呢?看看这个:w+@(w+.)?w+.com
这个又是什么意思?
w+@与之前一样
(w+.)?中的“ ? ”是匹配0次或1次括号分组内的匹配内容,"()" 则表示被括内容是一个分组,分组序号从pattern字符串起始往后依次排列。分组的概念非常重要,在后面 “匹配对象方法” 章节会着重介绍其如何使用。
w+.com与之前一样
因为是匹配0次或1次,那么就意味着括号内的部分是可有可无的,所以这个pattern就可能匹配两种邮箱格式。
“?”是0次或1次,那么 w+@(w+.)*w+.com 模式就更厉害了," * " 可以匹配0次或无限次。
re模块核心函数
上面简单的介绍了正则表达式的pattern是如何设置的,那么下一步我们就可以开始我们的提取工作了。在Python的re模块中有几个核心的函数专门用来进行匹配和查找。
compile()函数
函数定义: compile(pattern, flag=0)
函数描述:编译正则表达式pattern,然后返回一个正则表达式对象。
为什么要对pattern进行编译呢?《Python核心编程 》里面是这样解释的:
使用预编译的代码对象比直接使用字符串要快,因为解释器在执行字符串形式的代码前都必须把字符串编译成代码对象。
同样的概念也适用于正则表达式。在模式匹配发生之前,正则表达式模式必须编译成正则表达式对象。由于正则表达式在执行过程中将进行多次比较操作,因此强烈建议使用预编译。而且,既然正则表达式的编译是必需的,那么使用预编译来提升执行性能无疑是明智之举。re.compile()能够提供此功能。
原来是这样,由于compile的使用很简单,所以将在以下几个匹配查找的函数使用方法中体现。
match()函数
函数定义: match(pattern, string, flag=0)
函数描述:只从字符串的最开始与pattern进行匹配,匹配成功返回匹配对象(只有一个结果),否则返回None。
import re s1 = '我12345abcde' s2 = '.12345abcde' # pattern字符串前加 “ r ” 表示原生字符串 pattern = r'w.+' # 编译pattern pattern_compile = re.compile(pattern) # 对s1和s2分别匹配 result1 = re.match(pattern, s1) result2 = re.match(pattern, s2) print(result1) print(result2) >>> <_sre.SRE_Match object; span=(0, 11), match='我12345abcde'>
注意:
match函数是从最开始匹配的,意思是如果第一个字符就不匹配,那就直接玩完,返回None。
Python中pattern字符串前面的 " r " 代表了原生字符串的意思。
search()函数
函数定义: search(pattern, string, flag=0)
函数描述:与match()工作的方式一样,但是search()不是从最开始匹配的,而是从任意位置查找第一次匹配的内容。如果所有的字串都没有匹配成功,返回None,否则返回匹配对象。
import re s1 = '我12345abcde' s2 = '+?!@12345abcde' # pattern字符串前加 “ r ” 表示原生字符串 pattern = r'w.+' pattern_compile = re.compile(pattern) result1 = re.search(pattern_compile, s1) result2 = re.search(pattern_compile, s2) print(result1) print(result2) >>> <_sre.SRE_Match object; span=(0, 11), match='我12345abcde'> >>> <_sre.SRE_Match object; span=(4, 14), match='12345abcde'>
可以看到无论字符串最开始是否匹配pattern,只要在字符串中找到匹配的部分就会作为结果返回(注意是第一次匹配的对象)。
findall()函数
函数定义: findall(pattern, string [,flags])
函数描述:查找字符串中所有(非重复)出现的正则表达式模式,并返回一个匹配列表
import re s1 = '我12345abcde' s2 = '+?!@12345abcde@786ty' # pattern字符串前加 “ r ” 表示原生字符串 pattern = r'd+' pattern_compile = re.compile(pattern) result1 = re.match(pattern_compile, s2) result2 = re.search(pattern_compile, s1) result3 = re.findall(pattern_compile, s2) print(result1) print(result2) print(result3) >>> None >>> <_sre.SRE_Match object; span=(1, 6),
上面同时列出了match、search、findall三个函数用法。findall与match和search不同的地方是它会返回一个所有无重复匹配的列表。如果没找到匹配部分,就返回一个空列表。
来源:PY学习网:原文地址:https://www.py.cn/article.html