正则表达式的功能很多,除去之前介绍的验证(字符串能否由正则表达式匹配),还可以从某个字符串中提取出某个字符串能匹配的所有文本。

上一章提到,re.search()如果匹配成功,返回一个MatchObject对象。这个对象包含了匹配的信息,比如表达式匹配的结果,可以像例2-7那样,通过调用MatchObject.group(0)来获得。这个方法以后详细介绍,现在只需要了解一点:调用它可以得到表达式匹配的文本。

例2-7  通过MatchObject获得匹配的文本

#注意这里使用链式编程  
print re.search(r"\d{6}", "ab123456cd").group(0)  
123456   
print re.search(r"^<[^>]+>$", "<bold>").group(0)  
<bold>

这里再介绍一个方法:re.findall(pattern, string)。其中pattern是正则表达式,string是字符串。这个方法会返回一个数组,其中的元素是在string中依次寻找pattern能匹配的文本。

以邮政编码的匹配为例,假设某个字符串中包含两个邮政编码:zipcode1:201203, zipcode2:100859,仍然使用之前匹配邮政编码的正则表达式\d{6},调用re.findall()可以将这两个邮政编码提取出来,如例2-8。注意,这次要去掉表达式首尾的^和$,因为要使用正则表达式在字符串中寻找匹配,而不是验证整个字符串能否由正则表达式匹配。

例2-8  使用re.findall()提取数据

print re.findall(r"\d{6}", "zipcode1:201203, zipcode2:100859")  
['201203', '100859']  
 
#也可以逐个输出  
for zipcode in re.findall(r"\d{6}", "zipcode1:201203, zipcode2:100859"):  
    print zipcode
201203  
100859

借助之前的匹配各种tag的正则表达式,还可以通过re.findall()将某个HTML页面中所有的tag提取出来,下面以Yahoo首页为例。

首先要读入http://www.yahoo.com/的HTML源代码,在Python中先获得URL对应页面的源代码,保存到htmlSource变量中,然后针对匹配各类tag的正则表达式,分别调用re.findall(),获得各类tag的列表(因为这个页面中包含的tag太多,每类tag只显示前3个)。

因为这段程序的输出很多,在交互式界面下不方便操作和观察,建议将这些代码单独保存为一个.py文件,比如findtags.py,然后输入python findtags.py运行。如果输入python没有结果(一般在Windows下会出现这种情况),需要准确设定PATH变量,比如d:\Python\python。之后,就会看到例2-9显示的结果。

例2-9  使用re.findall()提取tag

#导入需要的package  
import urllib  
import re  
#读入HTML源代码  
sock = urllib.urlopen("http://yahoo.org/")  
htmlSource = sock.read()  
sock.close()  
#匹配,输出结果([0:3]表示取前3个)  
print "open tags:"  
print re.findall(r"<[^/>][^>]*[^/>]>", htmlSource)[0:3]  
print "close tags:"  
print re.findall(r"</[^>]+>", htmlSource) [0:3]  
print "self-closing tags:"  
print re.findall(r"<[^>/]+/>", htmlSource) [0:3]  
 
open tags:  
['<!DOCTYPE html>', '<html lang="en-US" class="y-fp-bg y-fp-pg-grad  bkt701">', '<!-- m2 template 0 -->']  
close tags:  
['</title>', '</script>', '</script>']  
self-closing tags:  
['<br/>', '<br/>', '<br/>']