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的现象

    • 为什么要用分组?
    • 把想要的内容放到分组当中
  • 如何取消分组优先

    #如果在写正则的时候由于不得以的原因 导致不要的内容也要写在分组中
    #(?:)取消这个分组的优先显示
    

预习内容

posted @ 2020-08-02 00:43  Redbean1231  阅读(74)  评论(0编辑  收藏  举报