正则表达式:正则表达式的模块是re,它的基本语法规则就是指定一个字符序列。
导入正则表达式:
import re
正则表达式常用字符集:
.:
#表示任意匹配
import re s = 'pyc py pyo' res = r'py.' print(re.findall(res,s)) 输出结果: ['pyc', 'py ', 'pyo']
[]:
(1)指定一个字符集:[abc];[a-z]
>>> s = 'tip top tap tep' >>> res = r't[io]p'
>>> re.findall(res,s)
['tip', 'top']
(2)元字符在[]中不起作用:[akm$]
(3)补齐匹配不在区间范围的字符:[^5] #取反,即:取出不是数字5的字符
^:
#它出现在非[]中含义是匹配行首;若^出现中[]中,则表示取反
>>> r = r'^abc' #以abc开头字符串 >>> re.findall(r,'aaabc') [] >>> re.findall(r,'abc3') ['abc'] >>> re.findall(r,'^abc3') []
$:
#它出现在非[]中含义是匹配行尾
>>> s = '123abc456eabc789' >>> re.findall(r'789$',s) ['789']
\:
#转义符
>>> r = r'\^abc' #转义后面的^为一个普通字符,并非匹配行首的意思 >>> re.findall(r,'^abc3') ['^abc'] >>> re.findall(r,'abc3') []
\d #匹配数字[0-9] \D #匹配非数字[^0-9] \s #匹配空白字符,如回车,空格等[\t\n\f\v] \S #匹配非空字符 [^\t\n\f\v] \w #匹配数字和字母 [0-9a-zA-Z] \W #匹配非数字和字母 [^0-9a-zA-Z]
例:
>>> r = r'010-\d{8}' #\d{8}表示数字重复8次 >>> re.findall(r,'010-123456789') ['010-12345678'] >>> re.findall(r,'010-1234567') []
|:
#任意匹配一个,它总是尝试匹配左边的表达式,一旦匹配成功则跳过匹配右边的表达式,如果|没有在括号()中,则它的范围是整个表达式。
abc|def 匹配的字符串为:abc 或者 def
*:
#将*前面的字符重复0次或多次
>>> r = r'ab*' >>> re.findall(r,'a') #重复b零次 ['a'] >>> re.findall(r,'ab') #重复b一次 ['ab'] >>> re.findall(r,'abb') #重复b两次 ['abb'] >>> re.findall(r,'abbbbbb') #重复多次b ['abbbbbb']
+:
#将+前面的字符重复1次或多次(即:至少重复一次)
>>> r = r'ab+' >>> re.findall(r,'a') [] >>> re.findall(r,'ab') ['ab'] >>> re.findall(r,'abbb') ['abbb']
?:
#将?前面的字符重复0次或1次,用于表示可选项,即可有可无的字符
>>> r = r'010-?\d{8}$' >>> re.findall(r,'010-12345678') ['010-12345678'] >>> re.findall(r,'01012345678') ['01012345678']
(.+?):
#提取单个位置的字符串
例1:提取字符串'a123b'中的'123'
import re str = 'a123b' r = r'a(.+?)b' res = re.findall(r,str) print(res)
输出结果:
['123']
例2:提取字符串'a123bc456d'中,从a到d之间数字部分
import re str = 'a123b456d' r = 'a(\d+)b(\d+)d' res = re.findall(r,str) print(res)
输出结果
[('123', '456')]
例3:匹配多行
import re str = 'a123\nb456\nd789' r = r'a(\d+).b(\d+).d(\d+)' res = re.findall(r,str,re.S) #加上re.S让.匹配包括换行符在内的所有字符 print(res)
输出结果:
[('123', '456', '789')]
{m}:
#m为数字 #重复{}前面字符m次
{m,n} m,n为数字 #表示最小重复m次,最多重复n次 >>> r = r'a{1,3}' >>> re.findall(r,'a') ['a'] >>> re.findall(r,'aa') ['aa'] >>> re.findall(r,'aaa') ['aaa'] >>> re.findall(r,'aaaa') ['aaa', 'a']
(?:):
#无捕获组:将一部分规则最为一个整体对它进行操作
(?#):
#注释:写入注释
特殊字符类:
. : #匹配除 "\n" 之外的任何单个字符,如果要匹配\n,使用[.\n]
\d: #匹配一个数字字符[0-9]
\D: #匹配非数字集合[^0-9]
\s: #匹配任何空白字符,包括空格,制表符,换页符等[\f\n\r\t\v]
\S: #匹配非空白字符[^\f\n\r\t\v]
\w: #匹配字母数字下划线任何单字符[A-Za-z0-9_]
\W: #匹配任何非单词字符[^A-Za-z0-9_]
编译正则表达式:可以实现匹配速度提高
>>> import re >>> p = re.compile('ab*') #编译正则表达式 >>> p.findall('abbbb') #调用 ['abbbb']
执行匹配:
(1)match():#匹配元素在该字符串中开始的位置,如果匹配则返回一个对象,否则返回为空。
>>> r = re.compile(r'cctv',re.I) >>> r.match('cctv hello') #匹配对象在起始位置 <_sre.SRE_Match object at 0x00000000032B15E0> >>> r.match('hello cctv') #匹配对象不在起始位置 >>> #返回空
(2)search() : #扫描整个字符串,并返回第一个匹配的项。
>>> cctv_re = re.compile(r'cctv',re.I) >>> cctv_re.search('hello cctv') <_sre.SRE_Match object at 0x00000000033305E0> >>> cctv_re.search('cctv hello') <_sre.SRE_Match object at 0x0000000003330648> >>> cctv_re.search('hello cctv hello') <_sre.SRE_Match object at 0x00000000033305E0> #只要匹配re规则,就会返回第一个匹配的对象,无论元素位置在哪。
(3)findall(): #返回字符串中所有匹配re的项。
模块级函数:
(1)sub() #替换
>>> r = r'c..v' >>> re.sub(r,'python','ccav cctv ccsv cccc') #r表示前面定义的正则表达式,'python'为替换后的字符串,'ccav cctv...'表示原字符串。 'python python python cccc' #匹配正则表达式的内容都会被替换
(2)subn() #替换多次
>>> s = 'ccav cctv ccsv ssrv svvv' >>> r = r's..v' >>> re.subn(r,'aaa',s,1) ('ccav cctv ccsv aaa svvv', 1) #只有第一个匹配到的项被替换成'aaa',虽然后svvv也符合re,但匹配次数设置的为是1,所以不替换。
(3)split() #切割
>>> ip = '192.168.1.1' >>> re.split(r'\.',ip) ['192', '168', '1', '1'] #以.分割字符串
编译标志:
(1)re.S #使.匹配包括行在内的所有字符,包括换行等字符
>>> import re >>> r = r'cctv.net' >>> re.findall(r,'cctv%net') ['cctv%net'] >>> re.findall(r,'cctvanet') ['cctvanet'] >>> re.findall(r,'cctv\nnet') [] >>> re.findall(r,'cctv\nnet',re.S) ['cctv\nnet']
(2)re.I #使匹配对大小写不敏感
>>> cctv_re = re.compile(r'cctv',re.I) #忽略大小写 >>> cctv_re.findall('CCTV') ['CCTV'] >>> cctv_re.findall('cctv') ['cctv'] >>> cctv_re.findall('ccTV') ['ccTV']
(3)re.L #使本地化识别匹配日、法语等
(4)re.M #多行匹配,影响^和$。当一个字符串有很多行时,匹配时就需要用M参数
>>> s = r''' hello cctv cctv hello hello cctv hello cctv hi ''' >>> r = r'^cctv' >>> re.findall(r,s) [] >>> s '\nhello cctv\ncctv hello\nhello cctv hello\ncctv hi\n' >>> re.findall(r,s,re.M) ['cctv', 'cctv']
(5)re.X #该标志通过给予你更灵活的格式,以便你将正则表达式写得更易于理解
>>> tel = r''' \d{3,4} -? \d{8} ''' >>> re.findall(tel,'010-12345678') [] >>> tel '\n\\d{3,4}\n-?\n\\d{8}\n' >>> re.findall(tel,'010-12345678',re.X) ['010-12345678']
分组:只提取分组部分内容
例1:匹配邮箱地址,结尾是.com或.cn
>>> email = r'\w+@\w+(\.com|\.cn)' >>> re.match(email,'aaa@bbbb.com') <_sre.SRE_Match object at 0x0000000003237558> >>> re.match(email,'aaa@bbbb.cn') <_sre.SRE_Match object at 0x00000000032375D0> >>> re.match(email,'aaa@bbbb.net') >>> >>> re.findall(email,'aaa@bbbb.com') ['.com'] #分组原因,返回分组的内容
例2:如果想提取s字符串中以cctv开头,后面的值
>>>s = ''' hello cctv cctv hello hello cctv hello cctv hi ''' >>> r = r'cctv (.+)' >>> re.findall(r,s) ['hello', 'hello', 'hi']
例3:小爬虫:下载贴吧或空间中所有图片
#!/usr/bin/python import re import urllib def getHTML(url): #下载整个链接的url page = urllib.urlopen(url) html = page.read() return html def getImg(html): #过滤,只下载.jpg的图片 reg = r'src="(.*?\.jpg)" width' imgre = re.compile(reg) #做编译,为了运行的更快 imglist = re.findall(imgre,html) x = 0 for imgurl in imglist: urllib.urlretrieve(imgurl,'%s.jpg' % x)
x += 1 html = getHTML('http://tieba.baidu.com/p/4760488708') getImg(html)
正则表达式常用方式:
整数(包括正整数和负整数): ^-?\d+$ 正整数: ^[0-9]*[1-9][0-9]*$ 负整数:^-[0-9]*[1-9][0-9]*$ 非正整数(负整数和零):^((-\d+)|0+))$ 非负整数(正整数和零):^(\d)|(0+)$ 正浮点数:^((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$ 负浮点数:^((-((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$ 非负浮点数:^\d+(\.\d+)?$ 非正浮点数:^((-\d+\.\d+)?)|(0+(\.0+)?))$
英文字符串: ^[a-zA-Z]+$ 英文大写字符串: ^[A-Z]+$ 英文小写字符串: ^[a-z]+$ 英文加数字字符串: ^[a-zA-Z0-9]+$ 英文数字加下划线: ^\w+$ E-mail地址: ^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$ URL: ^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$ 或: ^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$ 邮政编码: ^[1-9]\d{5}$ 中文: ^[\u0391-\uFFE5]+$ 电话号码: ^((\d2,3)|(\d{3}\-))?(0\d2,3|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$ 手机号码: ^((\d2,3)|(\d{3}\-))?13\d{9}$ 匹配首尾空格: (^\s*)|(\s*$) 匹配HTML标记: <(.*)>.*<\/\1>|<(.*) \/> 匹配空行: \n[\s| ]*\r 提取信息中的网络链接:(h|H)(r|R)(e|E)(f|F) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)? 提取信息中的邮件地址:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 提取信息中的图片链接:(s|S)(r|R)(c|C) *= *('|")?(\w|\\|\/|\.)+('|"| *|>)? 提取信息中的IP地址:(\d+)\.(\d+)\.(\d+)\.(\d+) 提取信息中的中国手机号码:(86)*0*13\d{9} 提取信息中的中国固定电话号码:(\d3,4|\d{3,4}-|\s)?\d{8} 提取信息中的中国电话号码(包括移动和固定电话):(\d3,4|\d{3,4}-|\s)?\d{7,14} 提取信息中的中国邮政编码:[1-9]{1}(\d+){5} 提取信息中的浮点数(即小数):(-?\d*)\.?\d+ 提取信息中的任何数字 :(-?\d*)(\.\d+)? IP:r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" 电话区号:/^0\d{2,3}$/ 腾讯QQ号:^[1-9]*[1-9][0-9]*$ 帐号(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$