python第十八天
python第十八天
正则表达式
# 什么是正则表达式
# 一套规则 - 匹配字符串的
# 能做什么
# 1.检测一个输入的字符串是否合法 -- web开发项目 表单验证
# 用户输入一个内容的时候,我们要提前做检测
# 能够提高程序的效率并且减轻服务器的压力
# 2.从一个大文件中找到所有符合规则的内容 -- 日志分析\爬虫
# 能够高效的从一大段文字中快速找到符合规则的内容
# 正则规则
# 所有的规则中的字符就可以刚好匹配到字符串中的内容
# 字符组 描述的是一个位置上能出现的所有可能性
# 接受范围,可以描述多个范围,连着写就可以了
# [abc] 一个中括号只表示一个字符位置
# 匹配a或者b或者c
# [0-9] 根据ascii进行范围的比对
# [a-z]
# [A-Z]
# [a-zA-Z] 大小写
# [0-9a-z]
# [0-9a-zA-Z_]
# 在正则表达式中能够帮助我们表示匹配的内容的符号都是正则中的 元字符
# [0-9] --> \d 表示匹配一位任意数字 digit
# [0-9a-zA-Z_] --> \w 表示匹配数字字母下划线 word
# 空格 -->
# tab --> \t
# enter回车 --> \n
# 空格,tab和回车 --> \s 表示所有空白 包括空格 tab和回车
# 元字符 -- 匹配内容的规则
# [] [^]字符组和非字符^表示字符的开始
# \d
# \w
# \s
# \t
# \n
# \W 非数字字母下划线
# \D 非数字
# \S 非空白
# [\d] \d
# [\d\D] [\w\W] [\s\S] 表示匹配所有
# . 匹配除了换行符之外的所有
# [^\d] 匹配所有的非数字
# [^1] 匹配所有的非数字
# ^ 匹配一个字符串的开始
# $ 匹配一个字符串的结尾
# a表达式|b表达式 匹配a或者b表达式中的内容,如果匹配a成功了,不会继续和b匹配
# 所以,如果两个规则有重叠部分,总是把长的放在前面
# () # 约束 | 描述的内容的范围问题
# www\.oldboy\.com|www\.baidu\.com|www\.jd\.com|www\.taobao\.com
# www\.(oldboy|baidu|jd|taobao)\.com
# 记忆元字符 : 都是表示能匹配哪些内容,一个元字符总是表示一个字符位置上的内容
# \d \w \s \t \n \D \W \S
# [] [^] .
# ^ $
# | ()
# 量词
# {n} 表示匹配n次
# {n,} 表示匹配至少n次
# {n,m}表示至少匹配n次,至多m次
# ? 表示匹配0次或1次 {0,1}
# + 表示1次或多次 {1,}
# * 表示0次或多次 {0,}
# 匹配0次
# 整数 \d+
# 小数 \d+\.\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 表示匹配任意字符 任意多次数 遇到最后一个x才停下来
# 非贪婪(惰性)匹配
# .*?x 表示匹配任意字符 任意多次数 但是一旦遇到x就停下来
# 转义符
# 原本有特殊意义的字符,到了表达它本身的意义的时候,需要转义
# 有一些有特殊意义的内容,放在字符组中,会取消它的特殊意义
# [().*+?] 所有的内容在字符组中会取消它的特殊意义
# [a\-c] -在字符组中表示范围,如果不希望它表示范围,需要转义,或者放在字符组的最前面\
练习用正则表达式18/15位身份证号码
# 18/15位的身份证号
# 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})$
# [1-9]\d{14}(\d{2}[\dx])?
# ^[1-9]\d{14}(\d{2}[\dx])?$
re模块
import re
# ret = re.findall('\d+','19740ash93010uru')
# print(ret)
#
# ret = re.search('\d+','19740ash93010uru')
# print(ret) # 变量
# if ret:
# print(ret.group())
# 预习一个现象并且找到答案 - 分组有关系()
# findall 还是按照完整的正则进行匹配,只是显示括号里匹配到的内容
# ret = re.findall('9\d\d','19740ash93010uru')
# print(ret)
# search 还是按照完整的正则进行匹配,显示也显示匹配到的第一个内容,但是我们可以通过给group方法传参数
# 来获取具体分组中的内容
# ret = re.search('9(\d)(\d)','19740ash93010uru')
# print(ret) # 变量
# if ret:
# print(ret.group())
# print(ret.group(1))
# print(ret.group(2))
# findall
# 取所有符合条件的,优先显示分组中的
# search 只取第一个符合条件的,没有优先显示这件事儿
# 得到的结果是一个变量
# 变量.group() 的结果 完全和 变量.group(0)的结果一致
# 变量.group(n) 的形式来指定获取第n个分组中匹配到的内容
# 为什么在search中不需要分组优先 而在findall中需要?
# 加上括号 是为了对真正需要的内容进行提取
# ret = re.findall('<\w+>(\w+)</\w+>','<h1>askh930s02391j192agsj</h1>')
# print(ret)
# search
# ret = re.search('<(\w+)>(\w+)</\w+>','<h1>askh930s02391j192agsj</h1>')
# print(ret.group())
# print(ret.group(1))
# print(ret.group(2))
# 为什么要用分组,以及findall的分组优先到底有什么好处
exp = '2-3*(5+6)'
# a+b 或者是a-b 并且计算他们的结果
# ret = re.search('\d+[+]\d+',exp)
# print(ret)
# a,b = ret.split('+')
# print(int(a)+int(b))
# ret = re.search('(\d+)[+](\d+)',exp)
# print(ret)
# print(ret.group(1))
# print(ret.group(2))
# print(int(ret.group(1)) + int(ret.group(2)))
# 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://movie.douban.com/top250?start=0&filter=')
# print(ret.content.decode('utf-8'))
# 分组和findall的现象
# 为什么要用分组?
# 把想要的内容放分组里
# 如何取消分组优先
# 如果在写正则的时候由于不得已的原因 导致不要的内容也得写在分组里
# (?:) 取消这个分组的优先显示