一、定义
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
re 模块使 Python 语言拥有全部的正则表达式功能。
二、Python字符匹配
>>> import re
>>> r=r'ab'
>>> print re.findall(r,'abcdefgabcd')
['ab', 'ab']
注意:如果有元字符,注意使用转义符'\'
e.g:
>>> r=r'1\*2'
>>> print re.findall(r,'1*2abd*1*2345')
['1*2', '1*2']
>>> r3=r'1\^123'
>>> print re.findall(r3,'1^12345')
['1^123']
三、Python元字符介绍
^ 匹配行首
>>> r2=r'^123'
>>> print re.findall(r2,'12345')
['123']
$ 匹配行尾
>>> r2=r'123$'
>>> print re.findall(r2,'12345123')
['123']
. 匹配单字符
>>> r=r'34.5'
>>> print re.findall(r,'345534523425')
['3455', '3425']
[] 匹配指定的一个字符集
1.
>>> r=r'a[a-zA-Z0-9]c'
>>> re.findall(r,'abcaBca9ccfg')
['abc', 'aBc', 'a9c']
2.
>>> r=r'[1a]' #匹配1或a
>>> re.findall(r,'1ac11aac1acc')
['1', 'a', '1', '1', 'a', 'a', '1', 'a']
[^ ] 补集匹配不在区间范围内的字符,注意^放在前面
>>> r=r'a[^0-9]c'
>>> re.findall(r,'abcaBca9ccfg')
['abc', 'aBc']
四、Python特殊意义字符
\d 代表数字[0-9]
>>> r=r'a\dc'
>>> re.findall(r,'abcaBca9ccfg')
['a9c']
\D 非数字
>>> r=r'a\Dc'
>>> re.findall(r,'abcaBca9ccfg')
['abc', 'aBc']
\s 空白字符
>>> r=r'a\sc'
>>> re.findall(r,'a caBca9ccfg')
['a c']
\S 非空白字符
>>> r=r'a\Sc'
>>> re.findall(r,'a caBca9ccfg')
['aBc', 'a9c']
\w 单词字符[a-zA-Z0-9_]
>>> r=r'a\wc'
>>> re.findall(r,'abcaBca5ca*ca_c')
['abc', 'aBc', 'a5c', 'a_c']
\W 非单词字符
>>> r=r'a\Wc'
>>> re.findall(r,'abca*ca5ca ca#ca_c')
['a*c', 'a c', 'a#c']
{} 前一个字符的重复的次数:前一个字符在一个范围内的重复次数
1.
>>> r=r'a{2}c'
>>> re.findall(r,'aac,1ac,2aaaac')
['aac', 'aac']
2.
>>> r=r'a{1,3}c'
>>> re.findall(r,'ac,aac,aaac,aaaac')
['ac', 'aac', 'aaac', 'aaac']
* 将前一字符匹配大于等于0次,{0,}效果等价于*
>>> r=r'a*c'
>>> re.findall(r,'c,ac,aac,aaac')
['c', 'ac', 'aac', 'aaac']
+ 将前一字符匹配大于等于1次,{1,}效果等价于+
>>> r=r'a+c'
>>> re.findall(r,'ac,aac,abacc,aaac')
['ac', 'aac', 'ac', 'aaac']
>>> r=r'.+' #.表示任意字符
>>> print re.findall(r,'welcome')
['welcome']
? 将前一字符匹配0次或1次,表示是否出现,{0,1}效果等价于?
>>> r=r'a?c'
>>> re.findall(r,'c,ac,aac,aaaac')
['c', 'ac', 'ac', 'ac']
*? 尽可能少的匹配
>>> r=r'ab*?'
>>> re.findall(r,'abbbbbbbbbb')
['a']
{m,n} #多余拆分
>>> r=r'a{1,3}'
>>> re.findall(r,'a,aa,aaa,aaaa,aaaaa')
['a', 'aa', 'aaa', 'aaa', 'a', 'aaa', 'aa']
() 分组
>>> r=r'(.com.cn|.com|.cn)'
>>> re.findall(r,'123@qq.com,234@qq.com,345@qq.cn')
['.com', '.com', '.cn']
练习:
利用分组和特殊字符匹配邮箱,注意把'\.com\.cn'放在前面,整体加上括号作为一个大的分组处理方便看出来匹配到的是哪个
1.匹配qq邮箱
2.
五、Python正则常用函数
compile 编译后执行速度更快,findall 返回匹配列表
>>> r=r'a[bcd]e'
>>> p=re.compile(r)
>>> p.findall('abe,ace,ade,afe')
['abe', 'ace', 'ade']
match 匹配字符串开头,返回第一个匹配的内容
>>> r=r'(a[bcd]e)'
>>> res=re.match(r,'age,ace,ade,afe')
>>> print res.groups()
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
print res.groups()
AttributeError: 'NoneType' object has no attribute 'groups'
>>> res=re.match(r,'abe,ace,ade,afe')
>>> print res.groups()
('abe',)
search 匹配字符串全文,返回第一个匹配的内容
>>> r=r'(a[bcd]e)'
>>> res=re.search(r,'age,ace,ade,afe')
>>> print res.groups()
('ace',)
我们可以使用group(num)或 groups()匹配对象函数来获取匹配表达式。
group(num=0) 匹配的整个表达式的字符串;
group()可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从1到所含的小组号。
e.g:
>>> r=r'(a[bcd]e) or (a[def]g)'
>>> res=re.match(r,'abe or adg')
>>> print res.group()
abe or adg
>>> print res.group(1)
abe
>>> print res.group(2)
adg
>>> print res.group(1,2)
('abe', 'adg')
>>> print res.groups()
('abe', 'adg')
sub 字符串正则替换,返回替换字符串
1.
>>> re.sub(r'a..d','python','abcd,acd,namnd')
'python,acd,npython'
2.指定替换次数
>>> re.sub(r'a..d','python','abcd,acd,namnd',1)
'python,acd,namnd'
subn 字符串正则替换,返回元组(替换字符串,替换次数)
>>> re.subn(r'a..d','python','abcd,acd,namnd')
('python,acd,npython', 2)
split 返回切割后的列表
1.
>>> re.split(r'\+','12+34-56*78/90')
['12', '34-56*78/90']
2.
>>> re.split(r'[\+\-\*\/]','12+34-56*78/90')
['12', '34', '56', '78', '90']
应用:
1. 正则匹配身份证号
现在国家统一规定18位身份证:地址码(1+5)+ 出生日期码(8)+ 顺序码(3)+ 校验码X(1)-----------------------重庆市(500000)
2. 写一个网页爬虫,下载网页中的图片(下载用urllib.urlretrieve) ------------------------http://tieba.baidu.com/p/4114581614
e.g:
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
re 模块使 Python 语言拥有全部的正则表达式功能。
二、Python字符匹配
>>> import re
>>> r=r'ab'
>>> print re.findall(r,'abcdefgabcd')
['ab', 'ab']
注意:如果有元字符,注意使用转义符'\'
e.g:
>>> r=r'1\*2'
>>> print re.findall(r,'1*2abd*1*2345')
['1*2', '1*2']
>>> r3=r'1\^123'
>>> print re.findall(r3,'1^12345')
['1^123']
三、Python元字符介绍
^ 匹配行首
>>> r2=r'^123'
>>> print re.findall(r2,'12345')
['123']
$ 匹配行尾
>>> r2=r'123$'
>>> print re.findall(r2,'12345123')
['123']
. 匹配单字符
>>> r=r'34.5'
>>> print re.findall(r,'345534523425')
['3455', '3425']
[] 匹配指定的一个字符集
1.
>>> r=r'a[a-zA-Z0-9]c'
>>> re.findall(r,'abcaBca9ccfg')
['abc', 'aBc', 'a9c']
2.
>>> r=r'[1a]' #匹配1或a
>>> re.findall(r,'1ac11aac1acc')
['1', 'a', '1', '1', 'a', 'a', '1', 'a']
[^ ] 补集匹配不在区间范围内的字符,注意^放在前面
>>> r=r'a[^0-9]c'
>>> re.findall(r,'abcaBca9ccfg')
['abc', 'aBc']
四、Python特殊意义字符
\d 代表数字[0-9]
>>> r=r'a\dc'
>>> re.findall(r,'abcaBca9ccfg')
['a9c']
\D 非数字
>>> r=r'a\Dc'
>>> re.findall(r,'abcaBca9ccfg')
['abc', 'aBc']
\s 空白字符
>>> r=r'a\sc'
>>> re.findall(r,'a caBca9ccfg')
['a c']
\S 非空白字符
>>> r=r'a\Sc'
>>> re.findall(r,'a caBca9ccfg')
['aBc', 'a9c']
\w 单词字符[a-zA-Z0-9_]
>>> r=r'a\wc'
>>> re.findall(r,'abcaBca5ca*ca_c')
['abc', 'aBc', 'a5c', 'a_c']
\W 非单词字符
>>> r=r'a\Wc'
>>> re.findall(r,'abca*ca5ca ca#ca_c')
['a*c', 'a c', 'a#c']
{} 前一个字符的重复的次数:前一个字符在一个范围内的重复次数
1.
>>> r=r'a{2}c'
>>> re.findall(r,'aac,1ac,2aaaac')
['aac', 'aac']
2.
>>> r=r'a{1,3}c'
>>> re.findall(r,'ac,aac,aaac,aaaac')
['ac', 'aac', 'aaac', 'aaac']
* 将前一字符匹配大于等于0次,{0,}效果等价于*
>>> r=r'a*c'
>>> re.findall(r,'c,ac,aac,aaac')
['c', 'ac', 'aac', 'aaac']
+ 将前一字符匹配大于等于1次,{1,}效果等价于+
>>> r=r'a+c'
>>> re.findall(r,'ac,aac,abacc,aaac')
['ac', 'aac', 'ac', 'aaac']
>>> r=r'.+' #.表示任意字符
>>> print re.findall(r,'welcome')
['welcome']
? 将前一字符匹配0次或1次,表示是否出现,{0,1}效果等价于?
>>> r=r'a?c'
>>> re.findall(r,'c,ac,aac,aaaac')
['c', 'ac', 'ac', 'ac']
*? 尽可能少的匹配
>>> r=r'ab*?'
>>> re.findall(r,'abbbbbbbbbb')
['a']
{m,n} #多余拆分
>>> r=r'a{1,3}'
>>> re.findall(r,'a,aa,aaa,aaaa,aaaaa')
['a', 'aa', 'aaa', 'aaa', 'a', 'aaa', 'aa']
() 分组
>>> r=r'(.com.cn|.com|.cn)'
>>> re.findall(r,'123@qq.com,234@qq.com,345@qq.cn')
['.com', '.com', '.cn']
练习:
利用分组和特殊字符匹配邮箱,注意把'\.com\.cn'放在前面,整体加上括号作为一个大的分组处理方便看出来匹配到的是哪个
1.匹配qq邮箱
>>> r=r'\d{5,11}@qq.com'
>>> re.findall(r,'89753@qq.com,897530015@qq.com,212345@qq.com')
['89753@qq.com', '897530015@qq.com', '212345@qq.com']
===============================
>>> r=r'\d{5,11}@\w+.\w+'
>>> re.findall(r,'89753@qq.com,897530015@qq.com,212345@qq.com')
['89753@qq.com', '897530015@qq.com', '212345@qq.com']
======================================
>>> >>> r=r'\w+@\w+.\w+'
>>> re.findall(r,'89753@qq.com,897530015@qq.com,fangw1015@qq.com')
['89753@qq.com', '897530015@qq.com', 'fangw1015@qq.com']
2.
>>> r=r'(\w+@\w+(\.com\.cn|.com|.cn))'
>>> re.findall(r,'89753@qq.com,897530015@suncco.com.cn')
[('89753@qq.com', '.com'), ('897530015@suncco.com.cn', '.com.cn')]
五、Python正则常用函数
compile 编译后执行速度更快,findall 返回匹配列表
>>> r=r'a[bcd]e'
>>> p=re.compile(r)
>>> p.findall('abe,ace,ade,afe')
['abe', 'ace', 'ade']
match 匹配字符串开头,返回第一个匹配的内容
>>> r=r'(a[bcd]e)'
>>> res=re.match(r,'age,ace,ade,afe')
>>> print res.groups()
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
print res.groups()
AttributeError: 'NoneType' object has no attribute 'groups'
>>> res=re.match(r,'abe,ace,ade,afe')
>>> print res.groups()
('abe',)
search 匹配字符串全文,返回第一个匹配的内容
>>> r=r'(a[bcd]e)'
>>> res=re.search(r,'age,ace,ade,afe')
>>> print res.groups()
('ace',)
我们可以使用group(num)或 groups()匹配对象函数来获取匹配表达式。
group(num=0) 匹配的整个表达式的字符串;
group()可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从1到所含的小组号。
e.g:
>>> r=r'(a[bcd]e) or (a[def]g)'
>>> res=re.match(r,'abe or adg')
>>> print res.group()
abe or adg
>>> print res.group(1)
abe
>>> print res.group(2)
adg
>>> print res.group(1,2)
('abe', 'adg')
>>> print res.groups()
('abe', 'adg')
sub 字符串正则替换,返回替换字符串
1.
>>> re.sub(r'a..d','python','abcd,acd,namnd')
'python,acd,npython'
2.指定替换次数
>>> re.sub(r'a..d','python','abcd,acd,namnd',1)
'python,acd,namnd'
subn 字符串正则替换,返回元组(替换字符串,替换次数)
>>> re.subn(r'a..d','python','abcd,acd,namnd')
('python,acd,npython', 2)
split 返回切割后的列表
1.
>>> re.split(r'\+','12+34-56*78/90')
['12', '34-56*78/90']
2.
>>> re.split(r'[\+\-\*\/]','12+34-56*78/90')
['12', '34', '56', '78', '90']
应用:
1. 正则匹配身份证号
现在国家统一规定18位身份证:地址码(1+5)+ 出生日期码(8)+ 顺序码(3)+ 校验码X(1)-----------------------重庆市(500000)
>>> r=r'(^[1-8][0-7]{2}\d{3}[12]\d{3}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}([0-9X])$)'
>>> print re.findall(r,'330726196507040016')
[('330726196507040016', '07', '04', '6')]
>>> print re.findall(r,'33070219630306041X')
[('33070219630306041X', '03', '06', 'X')]
2. 写一个网页爬虫,下载网页中的图片(下载用urllib.urlretrieve) ------------------------http://tieba.baidu.com/p/4114581614
e.g:
#coding=utf-8
import urllib,re,os
from selenium import webdriver
driver = webdriver.Firefox()
def init():
driver.maximize_window()
driver.get("http://tieba.baidu.com/p/4114581614")
driver.set_page_load_timeout(60)
def crawler():
content=driver.page_source
reg=r'src="(http://imgsrc.baidu.com/forum/w.+?\.jpg)"'
imglist=re.findall(reg,content)
print imglist
num=1
for imgurl in imglist:
print imgurl
imgname = "%03d" % num
urllib.urlretrieve(imgurl, "d:/py/img/food"+os.sep+str(imgname)+".jpg")
num+=1
def drop():
driver.quit()
if __name__ == '__main__':
init()
crawler()
drop()