Python基础学习笔记(18)正则表达式、re模块

Python基础学习(18)正则表达式

一、今日大纲

  • 正则表达式
  • re 模块

二、正则表达式

  1. 模块和实际工作时间的关系

    • time 模块和时间的关系

      ​ time 模块让我们更方便的完成和时间相关的操作,但是事件本身和 time 模块无关。

    • re 模块和正则表达式的关系

      ​ 有了 re 模块就可以在 Python 语言中操作正则表达式了。

  2. 正则表达式的定义

    正则表达式 Regular Expression 是一套用于匹配字符串的规则,它具有:

    • 检测一个输入的字符串是否合法——web 开发项目、表单验证

      • 用户输入一个内容的时候,我们提前做检测。

      • 能够提高程序的效率并且减轻服务器的压力。

    • 从一个大文件中找到所有符合规则的内容——日志分析、爬虫

      • 能够高效地从一大段文字中快速找到符合规则的内容。
  3. 字符组 Character Class

    描述的是一个位置上能出现的所有的可能性。

    • 一个中括号只表示一个字符位置,如[abc]表示的是匹配单个的ab或者c字符。
    • 可以根据ASCII码进行范围的比对,如[0-9][a-z]等,也可以用[a-zA-Z]等形式表示。
    • 匹配两位数字可以利用[1-9][0-9]的形式,以此类推。
  4. 元字符 Meta Character 和量词

    Meta Character/ 量词 功能
    [...] 匹配一位字符,以括号内容为准
    [^...] 匹配一位“非”字符
    \d 匹配一位任意数字
    \w 匹配一位数字字母下划线
    \t 匹配一位 table
    \n 匹配一位换行符
    \s 匹配一位空白字符
    \D 匹配一位非数字
    \w 匹配一位非数字字母下划线
    \S 匹配一位非空白字符
    | 或(把长的放在左边优先匹配)
    \ 转义字符
    () 分组,约束描述的内容的范围
    \b 匹配后面是空白的字符
    匹配n次
    匹配至少n次
    匹配至少n次,至多m次
    ? 匹配〇次或一次
    + 匹配一次或多次
    * 匹配〇次或多次
  5. 贪婪匹配和惰性匹配

    • 贪婪匹配:在量词范围允许的情况下,尽可能地多匹配内容。
    • 惰性匹配(非贪婪匹配):在量词范围允许的情况下,匹配到的内容相对最少,一般在量词后加?实现(元字符不可直接加?)。
  6. 转义字符的使用

    原本有特殊意义的字符,到了表达它本身的意义的时候,需要在前面加上转义字符;有一些有特殊意义的内容,放在字符组中,会取消它的特殊意义(-是特殊情况,可在[]内表示范围)。

    # 一些小栗子
    # 匹配任意长度的常数 \d+
    # 匹配小数:\d+\.\d+
    # 小数或整数: \d+\(.?\d+)?
    
    # 手机号的表示
    # ^1[3-9]%d{9}$
    
    # 18/15位的身份证号码
    # 以1-9开头,18位末尾有可能是X
    # ^[1-9]\d{14}(\d{2}[0-9x])?$
    

三、re 模块

主要介绍 re 模块的两个方法 findall()search()

  1. findall()search()的基本用法

    findall()会在目标中寻找到所有符合正则表达式的字符串,以列表形式返回;search()会在目标中将第一个匹配到的内容以对象形式返回可以通过group()方法返回匹配字符串,如果没有匹配字符串使用该方法会报错。

    ret = re.findall('\d+', '19532asdas123812838adasda')  # 找到全部
    print(ret)
    
    ret = re.search('\d+', '19532asdas123812838adasda')  # 只找一个
    if ret:
        print(ret.group())  # 找不到会报错
    
  2. 分组

    如果在findall()search()的正则表达式参数中添加小括号分组,findall()会按照正则表达式进行匹配,但是只会将括号所匹配内容加入列表,如果有多个括号,会将每组括号匹配内容放置于元组之中再依次加入列表;而search()也会按照正则表达式进行匹配,且将第一个匹配到的内容以对象形式返回,但是我们可以通过在group(n)方法中传入索引参数实现对多个括号分组的读取。

    # re.findall()还是按照完整的正则进行匹配,但是只显示括号里匹配到的内容,但是不能多个括号
    ret = re.findall('9(\d)\d', '19532asdas123812838adasda')
    print(ret)  # ['5']
    # re.search()还是按照完整的正则进行匹配,显示也显示匹配到的第一个内容,我们可以通过给group方法传参数
    ret = re.search('(9)(\d)(\d)', '19532asdas123812838adasda')
    print(ret)  # <_sre.SRE_Match object; span=(1, 4), match='953'>
    if ret:
        print(ret.group(0))  # 953
        print(ret.group(1))  # 9
        print(ret.group(2))  # 5
    
  3. 如何取消分组优先级

    在一些特殊场景中,如果因为正则表达式语法的原因,不得已将正则表达式的一部分放入分组,我们可以在该分组括号上以(?:...)形式取消分组的优先显示。

    # findall取消优先:?:
    ret = re.findall('1(\d)(\d)', '123124')
    print(ret)  # [('2', '3'), ('2', '4')]
    ret = re.findall('1(?:\d)(\d)', '123124')
    print(ret)  # ['3', '4']
    
  4. 应用场景

    • 方便读取

      # 为什么要用分组,以及findall的分组优先到底有什么好处
      exp = '2-3*(5+6)'
      # a+b 或者是 a-b 并且计算它们的结果
      ret = re.search('(\d+)[+](\d+)', exp)
      print(int(ret.group(1)) + int(ret.group(2)))
      
    • 在爬虫中进行字段的精确匹配和读取

      我们寻找了一个豆瓣网页,将它以HTML文件形式存储在项目目录中,我们现在读取它源码中的电影名字:

      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)
      # ['肖申克的救赎', '霸王别姬', '这个杀手不太冷', '阿甘正传', '美丽人生', '泰坦尼克号', '千与千寻', '辛德勒的名单', '盗梦空间', '忠犬八公的故事', '机器人总动员', '三傻大闹宝莱坞', '海上钢琴师', '放牛班的春天', '楚门的世界', '大话西游之大圣娶亲', '星际穿越', '龙猫', '教父', '熔炉', '无间道', '疯狂动物城', '当幸福来敲门', '怦然心动', '触不可及']
      

四、什么是爬虫

通过代码获取到一个网页的源码,要获取源码中嵌着的网页,并从网页中寻找到我们需要的内容,就需要依靠正则表达式来实现。

  • 下载 requests 模块:依次寻找目录 File -> Settings->Project->Project Interpreter,然后点击加号,寻找并 Install requests 模块,这时我们就已经成功导入了第三方模块 requests,利用 requests.get()即可获取网页的源码。

    import requests
    ret = requests.get('http://www.baidu.com')
    print(ret.content.decode('utf-8'))
    
    # <!DOCTYPE html>
    # <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道.......
    
posted @ 2020-07-16 23:11  Raigor  阅读(119)  评论(0编辑  收藏  举报