一. 正则表达式
正则表达式是对字符串操作的⼀种逻辑公式. 我们⼀般使⽤正则表达式对字符串进行匹配和过滤.
使⽤正则的优缺点:
优点: 灵活, 功能性强, 逻辑性强.
缺点: 上⼿难. ⼀旦上手, 会爱上这个东⻄
工具: 各⼤大⽂本编辑器⼀般都有正则匹配功能. 我们也可以去http://tool.chinaz.com/regex/进行在线测试.
正则表达式由普通字符和元字符组成
普通字符:包括大小写字母,数字,在匹配普通字符的时候直接写就可以
元字符:元字符才是正则表达式的灵魂,下面介绍几种主要的.
1.字符组--[]
2.简单元字符
. 匹配除换⾏符以外的任意字符 \w 匹配字母或数字或下划线 \s 匹配任意的空白符 \d 匹配数字 \n 匹配⼀个换⾏符 \t 匹配⼀个制表符 \b 匹配⼀个单词的结尾 ^ 匹配字符串的开始 $ 匹配字符串的结尾 \W 匹配⾮字⺟母或数字或下划线 \D 匹配⾮数字 \S 匹配⾮空⽩符 a|b 匹配字符a或字符b
[] 字符组
[^xxx] 非xxxx
^ 字符串的开始
$ 字符串的结束
| 或者
() 匹配括号内的表达式,也表示一个组
[...] 匹配字符组中的字符
[^...] 匹配除了了字符组中字符的所有字符
3.量词
* 重复零次或更多次 + 重复⼀次或更多次 ? 重复零次或⼀次 {n} 重复n次 {n,} 重复n次或更多次 {n,m} 重复n到m次
4.惰性匹配和贪婪匹配
贪婪匹配:
.* 匹配尽可能多的字符 .+ 匹配一次或更多次的字符 惰性:
.*?x 尽可能少的匹配 匹配到x结束
4.1 在量词中的*, +,{} 都属于贪婪匹配. 就是尽可能多的匹配到结果.
4.2 在使用.*后⾯面如果加了? 则是尽可能的少匹配. 表示惰性匹配
4.3 .*?x的特殊含义 找到下⼀个x为⽌(重点)
- 分组 在正则中使用()进行分组
- 转义 比如r’\n’
- re.S 干掉换行符
二.re模块
re模块是python提供的⼀套关于处理正则表达式的模块. import re
核心功能有四个:
1.findall 查找所有匹配结果
2.finditer 和findall差不多,但是返回的是迭代器 通过group()可以拿到迭代器的值
3.search 搜索 一旦匹配到结果直接返回,匹配不到结果,返回None 通过group()可以拿到返回值
4.match 匹配 从头开始匹配,开头没有匹配到就报错 通过group()可以拿到返回值
# re的工作是在python中执行正则表达式
import re
# # findall 查找匹配所有结果
# result = re.findall("\d+", "baby的电话号是: 185123456789")
# print(result) #返回列表['185123456789']
# print(result[0]) #拿到列表里面的值185123456789
# finditer 返回的是迭代器
# it = re.finditer("\d+", "baby123456789的电话号是: 185123456789")
# for el in it:
# print(el.group()) # group()拿到迭代器的值
# search 搜索, 查找
# 一旦匹配到结果. 直接返回, 如果匹配不到结果. 返回None
# result = re.search("\d", "宝宝的电话是5916")
# print(result) #<_sre.SRE_Match object; span=(6, 7), match='5'>
# print(result.group())#group()拿到匹配到的值5
# match匹配, 从头开始匹配. 相当于在你正则前面加了一个^
# result = re.match("\d+", "宝宝的电话是:157")
# print(result.group()) #报错
# result = re.match("\d+", "157宝宝的电话是:")
# print(result.group()) #返回结果157
# search和match的区别: search查找. 找到了结果就返回. match. 从头开始匹配.
在python中分组()的使用
()分组后,只返回()里面的内容,并且是一个列表
给组命名 (?P<name>)
# res=re.findall(r'abc\d+def','abc561889564123def') # print(res) #返回结果['abc561889564123def'] # res=re.findall(r'abc(\d+)def','abc561889564123def') # print(res) #返回结果['561889564123'] # res=re.findall(r'abc(\d+)(def)','abc561889564123def') # print(res) #返回结果[('561889564123', 'def')] res=re.findall(r'abc\d+(def)','abc561889564123def') print(res) #返回结果['def']
# result = re.finditer(r"姓名:(?P<name>.*?), 爱好:(?P<hobby>.*?),", "姓名:宝宝, 爱好:女,") # for el in result: # print(el.group("name"), el.group("hobby"))
- re.finditer(re,content,re.S) 必须加re.S
# # 爬取电影天堂 from urllib.request import urlopen import re content = urlopen("https://www.dytt8.net/html/gndy/dyzz/20181219/57954.html").read().decode("gbk") # # print(content) # #这里的re匹配后,只拿到()里面的内容,其他内容都过滤 reg = r'<div id="Zoom">.*?片 名(?P<name>.*?)<br />◎年 代(?P<years>.*?)<br />.*?◎上映日期(?P<date>.*?)<br />'+ \ '.*?◎主 演(?P<main>.*?)◎简 介.*?<td style="WORD-WRAP: break-word" bgcolor="#fdfddf"><a href="(?P<download>.*?)">' # it = re.finditer(reg, content, re.S) # re.S 去掉.里面的\n # for el in it: print(el.group("name")) print(el.group("years")) print(el.group("date")) print(el.group("main").replace("<br /> ", ", ")) print(el.group("download"))
re的一些其他操作
compile()编译 先编译正则,在执行
group() 获取数据
re.sub 替换
re.subn 替换计数
re.split 切片
# # 正则的常用操作 #1.切片 # result = re.split("\d+", "宝宝110来找你了. 你回头收拾收拾去119报道") # print(result) # 用正则替换 # s = re.sub("\d+", "__sb__", "宝宝110来找你了. 你回头收拾收拾去119报道") # print(s) # s = re.subn("\d+", "__sb__", "宝宝110来找你了. 你回头收拾收拾去119报道") # 替换了xxx次 # print(s) # code = "for i in range(10): print(i)" # c = compile(code, "", "exec") # 编译 # exec(c) # 快速执行 #re中compile的使用,先编译正则,在执行 # reg = re.compile(r"\d+") # 编译了一段正则. 加载了一段正则 # lst = reg.findall("呵呵, 宝宝才不去110呢.他要去120了") # print(lst) # # re.findall(r"\d+", "呵呵, 宝宝才不去110呢.他要去120了") # lst = re.findall(r"a(?:\d+)c", "a123456c") # 把括号python中的分组变成了原来正则表达式中的分组 # print(lst)