1 ```python 2 知识脉络: 3 # 在python中使用正则表达式 4 # 转义符 : 在正则中的转义符 \ 在python中的转义符 5 # re模块 6 # findall search match 7 # sub subn split 8 # compile finditer 9 # python中的正则表达式 10 # findall 会优先显示分组中的内容,要想取消分组优先,(?:正则表达式) 11 # split 遇到分组 会保留分组内被切掉的内容 12 # search 如果search中有分组的话,通过group(n)就能够拿到group中的匹配的内容 13 # 正则表达式进阶 14 # 分组命名 15 # (?P<name>正则表达式) 表示给分组起名字 16 # (?P=name)表示使用这个分组,这里匹配到的内容应该和分组中的内容完全相同 17 # 通过索引使用分组 18 # \1 表示使用第一组,匹配到的内容必须和第一个组中的内容完全相同 19 ``` 20 21 22 23 2021/11/15学习内容 24 25 1.学习大纲: a. re模块 b. 常用的方法 26 27 c. python中正则表达式的特点 28 29 d. time模块 30 31 e. random模块 32 33 34 35 36 37 a. re 模块 (1) 匹配 findall search match 38 39 (2) 替换 sub subn 40 41 (3) 切割 split 42 43 (4) 进阶方法 compile finditer 44 45 (1) 匹配. 46 47 ```python 48 import re 49 # 匹配一 findall (*****) 50 re.findall('正则表达式', '字符串') 51 返回值类型:'列表' 返回值个数:1个 返回值内容:如果匹配上了就返回一个列表对象如果匹配不上返回空列表 52 eg1: 53 ret1 = re.findall('\d+', '451355saddf5562') # 第一个是正则表达式,第二个参数是 54 print(ret1) 55 结果: ['451355', '5562'] 返回的是一个列表 56 ``` 57 58 ```python 59 import re 60 # 匹配二 search (*****) 61 re.search('正则表达式', '字符串') 62 返回值类型: 正则表达式的结果对象 返回值个数: 1个 返回值内容: 如果匹配上了就返回对象 如果匹配不上就返回None 63 eg2: 64 ret2 = re.search('\d+', '45132132asdhask13212') 65 print(ret2) 66 print(ret2.group()) 67 结果: <re.Match object; span=(10, 11), match='d'> 返回的是一个(正则匹配结果的)对象 68 结果: 45132132 # 只匹配一次结果,惰性机制 69 eg3: ret3 = re.search('\d+', 'sdferer') 70 print(ret3) 71 if ret3:print(ret3.group()) 72 结果: None 因为没有匹配到结果,所有返回None 73 ``` 74 75 ```python 76 import re 77 # 匹配三 match (**) 78 re.match('正则表达式', '字符串') 79 相当于 在search前面加^(只从开头位置匹配) 可以通过group()函数来查看返回的值 只匹配一次 80 ``` 81 82 (2) 替换 83 84 ```python 85 import re 86 # 替换一. sub (***) replace 'sads021'.replace('021', 'h') 将021替换成h 87 re.sub('替换的方式:正则表达式', '替换的结果','要替换字符串','次数') 88 # 如果不指定次数 默认 全部替换 89 re.subn('正则表达式', '要替换的内容','字符串') 返回一个元组 ('字符串', '替换的次数') 相当于返回符合的个数 90 eg1: 91 ret = re.sub('\d+', 'h', 'sads021') 将021替换成h 92 print(ret) 93 结果: sadsh 将字符串中的021替换成h 94 eg2: 95 ret = re.sub('\d+', 'h', 'sads021sdaf021dsf021') 96 print(ret) 97 结果: sadshsdafhdsfh 将字符串中的021全部替换h 98 eg3: 99 ret = re.subn('\d+','h','sdf1313sfa564q6fads') 100 print(ret) 101 结果: ('sdfhsfahqhfads', 3) 返回的是一个元组 ('新的字符串', '替换的次数') 102 ``` 103 104 (3) 切割 105 106 ```python 107 import re 108 # 切割 split(***) 109 返回的是一个列表 110 eg1: 111 ret = re.split('\d','alex83egon20taibai40') 112 print(ret) 113 结果: ['alex', '', 'egon', '', 'taibai', '', ''] 114 eg2: 115 print('yuxin/23/'.split('/')) 116 结果: ['yuxin', '23', ''] 117 eg3: 118 ret = re.split('\d+','alex83egon20taibai40') 119 print(ret) 120 结果: ['alex', 'egon', 'taibai', ''] 121 eg4: 122 ret = re.split('(\d+)','alex83egon20taibai40') 123 print(ret) 124 结果: ['alex', '83', 'egon', '20', 'taibai', '40', ''] 125 # 对比eg3和eg4 将正则表达式用分组阔起来 就可以显示切割的字符串 126 ``` 127 128 (4) 进阶方法 129 130 ```python 131 # 进阶方法 - 爬虫\自动化开发 132 # compile ***** 时间效率 133 # re.findall('-0\.\d+|-[1-9]+(\.\d+)?','alex83egon20taibai40') --> python解释器能理解的代码 --> 执行代码 134 # ret = re.compile('-0\.\d+|-[1-9]\d+(\.\d+)?') 135 # res = ret.search('alex83egon-20taibai-40') 136 # print(res.group()) 137 # 节省时间 : 只有在多次使用某一个相同的正则表达式的时候,这个compile才会帮助我们提高程序的效率 138 ``` 139 140 ```python 141 # finditer ***** 空间效率 142 # print(re.findall('\d','sjkhkdy982ufejwsh02yu93jfpwcmc')) 143 # ret = re.finditer('\d','sjkhkdy982ufejwsh02yu93jfpwcmc') 144 # for r in ret: 145 # print(r.group()) 146 ``` 147 148 c. python中正则表达式的特点 149 150 ```python 151 # 分组遇到findall 152 import re 153 eg1: 154 ret = re.findall('-0\.\d+|-[1-9]\d*(\.\d+)?','-1asdada-200') 155 print(ret) 156 结果: ['', ''] 当正则表达式中的分组遇到了findall会优先显示分组内匹配的内容 忽略其他分组外的匹配内容 157 eg2: 158 ret = re.findall('www.(baidu|oldboy).com','www.oldboy.com') 159 print(ret) 160 结果: ['oldboy'] 只会优先显示分组内匹配的内容,忽略分组外匹配的内容 161 # 如果解决这个问题 要求eg2中返回 www.oldboy.com 162 eg3: 163 ret = re.findall('www.(?:baidu|oldboy).com','www.oldboy.com') 164 print(ret) 165 结果: ['www.oldboy.com'] 只需要在分组括号内前面加?: (?:....) 就可以取消分组优先显示 166 ``` 167 168 ```python 169 # 分组遇见search 170 # ret = re.search('\d+(.\d+)(.\d+)(.\d+)?','1.2.3.4-2*(60+(-40.35/5)-(-4*3))') 171 # print(ret.group()) # 没有参数默认返回 整个匹配值 172 # print(ret.group(1)) 173 # print(ret.group(2)) 174 # print(ret.group(3)) 175 # group(参数) 参数对应的就是读取括号 一一对应 176 ``` 177 178 分组练习 179 180 ```python 181 import re 182 eg1: 183 ret = re.findall(r"\d+(?:\.\d+)?","1-2*(60+(-40.35/5)-(-4*3))") 184 print(ret) 185 结果: ['1', '2', '60', '40.35', '5', '4', '3'] 但是我们需求是只要整数 186 eg2: 187 ret = re.find(r"\d+(?:\.\d+)?|(\d+)","1-2*(60+(-40.35/5)-(-4*3))") 188 print(ret) 189 ret.remove('') 190 print(ret) 191 结果: ['1', '2', '60', '', '5', '4', '3'] 192 结果: ['1', '2', '60', '5', '4', '3'] 193 eg3: 194 ret = re.findall('>(\w+)<',r'<a>wahaha<\a>') 195 print(ret) 196 结果: ['wahaha'] 197 eg4: 198 ret = re.search(r'<(\w+)>(\w+)</(\w+)>',r'<a>wahaha</b>') 199 print(ret.group()) 200 print(ret.group(1)) 201 print(ret.group(2)) 202 结果 : <a>wahaha</b> 203 结果 : a 204 结果 : wahaha 205 ``` 206 207 分组命名 208 209 ```python 210 import re 211 eg1: 212 ret = re.search("<(?P<name>\w+)>\w+</(?P=name)>","<h1>hello</h1>") 213 print(ret.group('name')) 214 结果: h1 给分组命名了 保证了第一个分组和第三个分组内容一样 在分组前面 ?P 表示给分组命名 215 eg2: 216 ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>") 217 print(ret.group(1)) 218 结果: h1 也可以使用\1 表示内容与第一个分组一致 219 eg3: 220 ret = re.search(r'<(?P<tag>\w+)>(?P<c>\w+)</(\w+)>',r'<a>wahaha</b>') 221 print(ret.group()) 222 print(ret.group('tag')) 223 print(ret.group('c')) 224 结果: <a>wahaha</b> 225 结果: a 226 结果: wahaha 也可以使用group('分组名字')来调用 227 228 ``` 229 230 推荐书籍 <<正则指引>>