Day 019 正则表达式:re模块:findall:search
今日内容大纲
- 模块和实际工作的关系
- time模块和时间是什么关系
- re模块和正则表达式的关系
- 有了re模块就可以在python语言中操作正则表达式了
- 正则表达式 (重要!!!!!!!!!!!!)
- re模块
- 用途:
- 自动化运维与开发
- 爬虫
昨日内容回顾与作业讲解
- 基础数据类型:
- 流程控制:条件判断 循环
- 文件操作
- 函数:
- 基础
- 装饰器
- 带参数的装饰器(没学)
- 迭代器,生成器
- 递归函数(没学)
- 常用模块
- random
- hashlib
- time datetime
- collections
- sys
- os
- json\pickle
- re(没学)
- logging(没学)
- 包的导入(没学)
今日内容
-
什么是正则表达式
-
一套规则-匹配字符串的
-
-
正则表达式能做什么?
1.检测一个输入的字符串是否合法 --- web开发项目 表单验证 用户输入一个内容的时候,我们要提前做检测 能够提高程序的效率,并且减轻服务器的压力 2.能够高效的从一大段字符串中快速找到符合规则的内容 --- 日志分析\爬虫
-
正则规则:
-
所有的规则中的字符就可以刚好匹配到字符串中的内容
-
字符组 描述的是一个位置上能出现的所有可能性
接受范围,可以描述多个范围,连着写就可以 [abc] 一个中括号只能表示一个字符位置 匹配a或者b或者c [0-9] 根据Ascii码进行范围的比对 [a-z] 小写字母 [A-Z] 大写字母 [a-zA-Z] 大小写字母 [0-9a-zA-Z] 大小写字母加数字
-
-
在正则表达式中能够帮助我们表示匹配的内容的符号 都是正则的 元字符
[0-9] ---> \d [0-9a-zA-Z_] ---> \w 回车 ---> tab ---> \t enter回车 ---> \n 空格,回车,tab ---> \s
-
元字符 匹配内容的规则
[] [^] \d \w \s \t \n \W ---> 非数字 字母下划线 \D ---> 非数字 \S ---> 非空白 [\d] \d [\d\D] ---> 表示匹配所有 . ---> 匹配除了换行符之外的所有 [^\d] ---> 匹配所有的非数字 [^1] ---> 匹配所有的非数字 ^ ---> 匹配一个字符串的开始 $ ---> 匹配一个字符串的结尾 a表达式|b表达式 ---> 匹配a或者b表达式中的内容,如果匹配a成功了,不会继续和b匹配 所以,如果两个规则有重叠部分,总是把长的放在前面 () ---> 约束 描述的内容的范围问题 www\.(oldboy|baidu|jd)\.com
-
量词
{n} ---> 匹配n次 {n,} ---> 匹配至少n次 {n,m} ---> 匹配至少n次,至多m次 ? ---> 匹配0次或1次 要么有,要么没有 + ---> 表示1次或多次 * ---> 表示0次或多次
-
匹配0次
整数 \d+ 小数 \d\.\d+ 整数或小数 \d(\.\d+)?
-
例子:手机号码
1 3-9 11位 1[3-9]\d{9} 判断用户输入的内容是否合法,如果用户输入的对就能查到结果,如果输入的不对就不能查到结果 ^1[3-9]\d{9}$ 从一个大文件中找到所有符合规则的内容 1[3-9]\d{9}
-
贪婪匹配
# 在量词范围允许的情况下,尽量匹配多的内容 # .*x 表示匹配任意字符 任意多次数,直到遇到最后1个x才停下来
-
非贪婪(惰性)匹配
#.*?x 表示匹配任意字符,任意多次数,遇到第一个x就停下来
-
转义符
#原本有特殊意义的字符,到了表达他本身的意义的时候,就需要转义 #有一些特殊意义的内容,放在字符组中,会取消他的特殊意义 #[() . * + ?] 所有的内容在字符组中会取消他的特殊意义 #[a \ - c] -在字符组中表示范围,如果不希望他表示范围,需要转义,或者,放在字符组的最前面\最后面
-
re模块
-
findall
import re ret = re.findall('\d+','19740ash93010uru') print(ret) #['19740', '93010']
-
search
ret = re.search('\d+','19740ash93010uru') print(ret) #<re.Match object; span=(0, 5), match='19740'> if ret: print(ret.group()) #19740
-
findall的分组优先显示
- 取所有符合条件的,优先显示分组中的
# findall 还是按照完整的正则进行匹配,只是显示括号里面匹配到的内容 ret = re.findall('9\d\d','19740ash93010uru') print(ret) #['974', '930'] ret = re.findall('9(\d)\d','19740ash93010uru') print(ret) #['7', '3'] ret = re.findall('9(\d)(\d)','19740ash93010uru') print(ret) #[('7', '4'), ('3', '0')]
-
search中不存在分组优先
- 只取第一个符合条件的,没有优先选择这件事儿
- 得到的结果是一个变量
- 变量.group()的结果 完全和变量.group(0)的结果一致,全都显示
- 变量.group(n)的形式来指定获取第一个分组中匹配到的内容 (1)第一个分组 (2)第二个分组
search 还是按照完整的正则进行匹配,显示也显示匹配到的第一个内容,但是我们可以给group的方法传参 来获取具体分组中的内容 ret = re.search('9(\d)(\d)','19740ash93010uru') print(ret) #<re.Match object; span=(1, 4), match='974'> if ret: print(ret.group()) #974 print(ret.group(1)) #7 print(ret.group(2)) #4
-
为什么在search中不需要分组优先,而在findall中需要??
#如果我们要查找的内容在一个复杂的环境中 #我们要查的内容并没有一个突出的,与众不同的特色,甚至会和不需要的杂乱的数据混合在一起 #这个时候我们就需要把所有的数据都统计出来,然后对这个数据进行筛选,把我们真真需要的数据对应的正则#表达式用括号()圈起来 #这样我们就可以真正筛选出真正需要的数据了
加上括号 是为了对真正需要的内容进行提取 ret = re.search('<(\w+)>(\w+)</\w+>','<h1>askh930s02391j192agsj</h1>') if ret: print(ret.group()) #<h1>askh930s02391j192agsj</h1> print(ret.group(1)) #h1 print(ret.group(2)) #askh930s02391j192agsj
exp = '2-3*(5+6)' 提取a+b 或 a-b,并计算它们的结果 ret = re.search('\d+[+-]\d+',exp) print(ret) #<re.Match object; span=(0, 3), match='2-3'> a,b = ret.group().split('-') print(int(a) - int(b)) #太麻烦了 ret = re.search('(\d)+[+-](\d+)',exp) if ret: # print(ret.group()) #2-3 print(ret.group(1)) #2 print(ret.group(2)) #3 print(int(ret.group(1))-int(ret.group(2))) #-1 #豆瓣对电影名爬虫 with open('douban.html',encoding='utf-8')as f: content = f.read() ret = re.findall('<span class="title">(.*?)</span>(?:\s*<span class="title">.*?</span>)?',content) print(ret)
-
什么是爬虫??
-
通过代码获取到一个网页的源码
-
要的是源码中嵌在网页上的内容 --> 正则表达式
#获取源码 import requests ret = requests.get('https://www.baidu.com') print(ret.content.decode('utf-8'))
-
-
如何取消分组优先
#如果在写正则的时候由于不得以的原因 导致不要的内容也要写在分组中 #(?:)取消这个分组的优先显示
-
今日总结
-
元字符:
\d \s \w \t \n \D \S \W [] [^] ^ $ () |
-
量词:
{} 表示任意的次数,任意的次数范围,至少多少次 .*?x
-
贪婪匹配和非贪婪匹配:
总是在量词范围内尽量多匹配 - 贪婪 总是在量词范围内尽量少匹配 - 惰性 .*?x 匹配任意内容任意次数 遇到x就停止 .+?x 匹配任意内容至少1次 遇到x就停止
-
转义符问题:
. 有特殊的意义,取消特殊的意义\. 取消一个元字符的特殊意义有两种方法 在这个元字符前面加\ 对一部分字符生效,把这个元字符放在字符组里 [.()+?*]
-
例子:身份证号 15/18位
15位身份证 1-9 15 [1-9]\d{14} 18位身份证 1-9 16 0-9/x [1-9]\d{16}[\dx] [1-9]\d{16}[0-9x] [1-9]\d{16}[0-9x]|[1-9]\d{14} ^([1-9]\d{16}[0-9x]|[1-9]\d{14})$
-
分组和findall的现象
- 为什么要用分组?
- 把想要的内容放到分组当中
-
如何取消分组优先
#如果在写正则的时候由于不得以的原因 导致不要的内容也要写在分组中 #(?:)取消这个分组的优先显示