zoukankan      html  css  js  c++  java
  • 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 匹配一位数字字母下划线
      匹配一位 table
      匹配一位换行符
      s 匹配一位空白字符
      D 匹配一位非数字
      w 匹配一位非数字字母下划线
      S 匹配一位非空白字符
      | 或(把长的放在左边优先匹配)
      转义字符
      () 分组,约束描述的内容的范围
       匹配后面是空白的字符
      {n} 匹配n次
      {n,} 匹配至少n次
      {n,m} 匹配至少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>百度一下,你就知道.......
      
  • 相关阅读:
    python 并发编程 多进程 互斥锁 目录
    python 并发编程 多进程 互斥锁
    python 并发编程 多进程 守护进程
    python 并发编程 多进程 Process对象的其他属性方法 terminate与is_alive name pid 函数
    python 并发编程 多进程 Process对象的其他属性方法 join 方法
    python 并发编程 多进程 目录
    POJ 2253
    POJ 2255
    POJ 2250
    POJ 2248
  • 原文地址:https://www.cnblogs.com/raygor/p/13326418.html
Copyright © 2011-2022 走看看