正则表达式——数据提取
正则表达式的功能很多,除去之前介绍的验证(字符串能否由正则表达式匹配),还可以从某个字符串中提取出某个字符串能匹配的所有文本。
上一章提到,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/>']