正则表达式(匹配字符串)
web界面正则匹配工具:
http://tool.chinaz.com/regex/
元字符
1 . 匹配除换行符之外的任意字符 2 w 匹配数字字母下划线 3 d 匹配数字 4 匹配制表符 5 匹配换行符 6 s 匹配空白符(包含,空格,制表符和换行符) 7 单词的边界 8 W 匹配非数字字母下划线 9 S 匹配非空白符 10 D 匹配非数字 11 ^ 匹配开始符 12 $ 匹配结束符 13 | 或者,如果是有包含关系的,长的放左边 14 [] 匹配字符组,具体的范围 15 [^...] 匹配非字符组中的字符 16 () 匹配括号内的是一组 17 18 19 转义符 20 如果在测试工具中测试正常的代码拿到python中,由于转义符的问题搞不定,那么就直接在字符串外面+r 21 print('\\n') 22 print('\n') 23 print(r'\n') 24 print(r' ') 25 26 事例: 27 www.(baidu|google).com 28 [0-9] == [0123456789] #表示0到9的所有数 29 [a-z]/[A-Z] 表示a到z/A-Z所有英文字母 30 [A-Za-z0-9] 表示数字和大小写字母 31 32 33 量词 34 贪婪匹配: 尽可能多的匹配(默认模式) 35 {n} 匹配n次 36 {n,} 匹配至少n次至多无限次 37 {n,m} 匹配至少n次至多m次 38 * 匹配前面字符0次或多次 39 + 匹配前面字符1次或多次 40 非贪婪/惰性匹配 41 ? 匹配前面字符0次或1次(.*?) 42 abbbx 正则^ab+?x,如果正则是^ab+?结果则是ab 43 44 45 总结 46 正则表达式: 不仅仅要能匹配出对的,还要尽量避免匹配错误的,提高精准度 47 分组的作用: 分组也可以和量词连用,表示这一个组遵循某个量词的约束 48 49 常用的非贪婪匹配 50 *? 重复任意次,但尽可能少重复 51 .*? 匹配前边任意字符,尽可能少的匹配 52 +? 重复1次或更多次,但尽可能少重复 53 ?? 重复0次或1次,但尽可能少重复 54 .?x 取尽量少的任意字符,直到一个x出现
re的功能是在python中执行正则表达式
re模块下的常用方法
import re
re.findall 正则 待匹配字符串,列表,所有符合的项
re.search 变量.group取结果,只有一项结果
re.match 变量.group取结果,默认在正则之前加上^
re.finditer 把匹配的结果存放在迭代器中
re.findall('正则表达式','带匹配的字符')
1 re.findall('正则表达式','带匹配的字符') 2 ret = re.findall('d+','aaa83bbb38') 3 print(ret) 4 结果 5 ['83', '38'] 6 事例2 7 ret = re.findall('d','aaa83bbb38') 8 print(ret) 9 结果 10 ['8', '3', '3', '8'] 11 12 # ?:把括号python中的分组变成了原来正则表达式中的分组 13 lst = re.findall(r"a(?:d+)c", "a123456c") 14 l2 = re.findall(r"a(d+)c", "a123456c") 15 print(lst) 16 print(l2) 17 结果 18 ['a123456c'] 19 ['123456']
re.finditer() #返回一个存放匹配结果的迭代器,节省空间
1 ret = re.finditer('d+','linux83admin60yuan25') 2 print(ret) #直接打印返回的是一个迭代器 3 print(next(ret).group()) #查看第1个结果 4 for r in ret: #查看剩余的结果 5 print(r.group()) 6 结果 7 <callable_iterator object at 0x000001FF0EACEBA8> 8 83 9 60 10 25
search 搜索, 查找
一旦匹配到结果,直接返回,如果匹配不到结果,返回None
1 ret = re.search('d','aaa83bbb38') 2 print(ret) #返回的匹配结果,而不是具体的值 3 print(ret.group()) #从左到右找到第一个匹配的取出 4 结果 5 <_sre.SRE_Match object; span=(4, 5), match='8'> 6 8 7 8 ret = re.search('d+','aaa83bbb22') 9 print(ret.group()) 10 结果 11 83
match匹配,从头开始匹配,相当于在你正则前面加了一个^
1 ret = re.match('d+','83aaa222bbb38') 2 print(ret.group()) 3 等于 4 ret = re.search('^d+','83aaa222bbb38') 5 print(ret) 6 结果 7 83
search和match的区别:
search查找,找到了结果就返回
match,从头开始匹配
给分组正则匹配定义一个名字(?P<名字>正则表达式)
1 ret = re.finditer(r'姓名:(?P<name>.*?),地址:(?P<address>.*?),','姓名:bob,地址:迪拜,年龄:18') 2 for i in ret: 3 print(i.group('name'),i.group('address')) 4 结果 5 bob 迪拜
re.split():分割
1 st = 'linux83admin60yuan25test' 2 ret = re.split('d+',st) #按照一个或多个数字进行分割 3 print(ret) 4 结果 5 ['linux', 'admin', 'yuan', 'test']
sub用正则替换
1 s = 'linux83admin60yuan25' 2 ret = re.sub('d+','_|_',s,1) #将一个或多个数字替换为_|_,1表示只替换1个,以字符串形式返回 3 print(ret) 4 结果 5 linux_|_admin60yuan25
subn显示替换次数
1 ret = re.subn('d+','_|_',s) #将一个或多个数字替换为_|_,以元组形式返回 2 print(ret) 3 结果 4 ('linux_|_admin_|_yuan_|_', 3)
re.compile():编译后引用正则匹配(返回列表)
1 ret = re.compile('d+') #将正则编译成一个正则对象,匹配一个或多个数字 2 lst = ret.findall('linux83admin60yuan25') 3 print(lst) 4 在多次执行同一个正则表达式的时候compile事先编译
案例:爬取电影天堂
1 import re 2 from urllib.request import urlopen 3 4 content = urlopen("https://www.dytt8.net/html/gndy/dyzz/20181228/57986.html").read().decode("gbk") 5 # print(content) 6 7 reg = r'<div id="Zoom">.*?片 名(?P<name>.*?)<br />◎年 代(?P<years>.*?)<br />.*?◎上映日期(?P<date>.*?)<br />'+ 8 '.*?◎主 演(?P<main>.*?)◎简 介.*?<td style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<download>.*?)">' 9 10 it = re.finditer(reg, content, re.S) # re.S 去掉.里面的 11 12 for el in it: 13 print(el.group("name")) 14 print(el.group("years")) 15 print(el.group("date")) 16 print(el.group("main").replace("<br /> ", ", ")) 17 print(el.group("download")) 18 19 结果 20 黄金兄弟 / 新古惑仔 / 新版古惑仔 / 黄金七十二小时 21 2018 22 2018-09-20(中国香港) / 2018-09-21(中国) 23 郑伊健 Ekin Cheng , 陈小春 Jordan Chan , 谢天华 Michael Tse , 钱嘉乐 Kar Lok Chin , 林晓峰 Jerry Lamb , 曾志伟 Eric Tsang , 佘诗曼 Charmaine Sheh , 张雅玫 Yamei Zhang <br /><br /> 24 ftp://ygdy8:ygdy8@yg45.dydytt.net:8373/阳光电影www.ygdy8.com.黄金兄弟.BD.720p.粤语中字.mkv
其他
1 事例1 2 ret = re.findall(r'd+(.d+)?','2.34+666.87') 3 print(ret) 4 结果 5 ['.34', '.87'] 6 #d+ = 2 (.d+) = .34 7 #d+ = 666 (.d+) = .87 8 #findall 优先显示分组中匹配到的内容 9 10 #如果想匹配浮点数就要把默认的非婪模式改为?:贪婪模式 11 ret = re.findall(r'd+(?:.d+)?','2.34+666.87') 12 print(ret) 13 结果 14 ['2.34', '666.87'] 15 16 17 事例2 18 ret = re.findall('www.(?:baidu|google).com','www.baidu.com') 19 print(ret) 20 结果 21 ['www.baidu.com'] 22 23 ret = re.findall('www.(baidu|google).com','www.baidu.com,www.google.com') 24 print(ret) 25 结果 26 ['baidu', 'google'] 27 28 29 ()组事例 30 ret = re.search('(www).(baidu|google).(com)','www.baidu.com,www.google.com') 31 print(ret) 32 print(ret.group()) 33 print(ret.group(0)) 34 print(ret.group(1)) 35 print(ret.group(2)) 36 print(ret.group(3)) 37 结果 38 <_sre.SRE_Match object; span=(0, 13), match='www.baidu.com'> 39 www.baidu.com 40 www.baidu.com 41 www 42 baidu 43 com