Python爬虫实践 —— Regular Expressions 正则表达式语法

示例:

RE最常用的功能之一,提交表单。例如:

用户注册表单时,只允许用户名包含字符、数字、下划线和连接字符(-),并设置用户名的长度为3-15个字符

 匹配模板为 ^[a-z 0-9 _-]{3,15}$

作用:

1.数据验证,测试字符串内的模式是否匹配。

2.替换文本,可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。

3.基于模式匹配从字符串中提取子字符串,可以查找文档内或输入域内特定的文本。

语法:

构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与运算符可以将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。

正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。

模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

  字符:

  1.普通字符

    普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。

  2.元字符

    (1)非打印字符 / 简写字符集

      f 匹配一个换页符

       匹配一个换行符

       匹配一个回车符

       匹配一个制表符

      v 匹配一个垂直制表符

      s 匹配任何空白字符,包括空格、制表符、换页符等等。==f v

      S 匹配任何非空白字符。==[^f v]

      d 匹配一个数字字符。等价于 [0-9]

      D 匹配一个非数字字符。等价于 [^0-9]

      w 匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'  

      W 匹配非字母、数字、下划线。等价于 '[^A-Za-z0-9_]'

    (2)特殊字符。(匹配特殊字符需要加 转义)

      $ 匹配输入字符串的结尾位置。

      ( ) 子表达式首位标记

      *  匹配前面的子表达式零次或多次。=={0,}

      + 匹配前面的子表达式一次或多次。=={1,}

      . 匹配除换行符 之外的任何单字符。

      [ 标记一个中括号表达式的开始。

      ? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。=={0,1}

       将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。

      ^ 匹配输入字符串的开始位置,在方括号表达式中使用时为逻辑非。

      { 标记限定符表达式的开始。

      | 指明两项之间的一个选择。逻辑或。

    (3)限定符

      *  匹配前面的子表达式零次或多次。=={0,}

      + 匹配前面的子表达式一次或多次。=={1,}

      ? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。=={0,1}

      {n} n 是一个非负整数。匹配确定的 n 次。

      {n,} n 是一个非负整数。至少匹配n 次。

      {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。

    (4)定位符 / 锚点 

      ^ == A 匹配输入字符串开始的位置。

      $ ==  匹配输入字符串结尾的位置。

       匹配一个单词边界,即字与空格间的位置。示例:标记,英文单词和空格之间为单词边界。 'er' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

      B 非单词边界匹配。示例:'erB' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

  匹配规则:

    (1)基本匹配

      once  ^once  bucket$   ^bucket$

    (2)字符集簇

      字符集与否定字符集  [0-9a-zA-Z] == w  [^0-9a-zA-Z] == W

    (3)特征标群与重复匹配

      (....) 结合 | 或运算符 

        "(c|g|p)ar" => The car is parked in the garage.

        "(T|t)he|car" => The car is parked in the garage.

      后面跟着元字符 +*? {m}{m,}{m,n} 的,用来指定匹配子模式的次数。

    (4)零宽度断言

      断言其实也是一种描述位置的元字符,它指定的是符合(?=exp)规则的位置。

        即通过exp子式确定校验位置,

        < 是否存在确定匹配校验位置后还是校验位置前的内容,

        = 和 ! 确定是否正负(符合还是不符合)匹配。

      零宽度断言按 (正/负) 向,(先行 / 后发) 分为四个:

        先行正 (?=exp)   匹配T/t he 后面跟空格 s fat

          "(T|t)he(?=sfat)" => The fat cat sat on the mat.

         先行负 (?!exp)  匹配T/t he 后面不跟空格 s fat

          "(T|t)he(?!sfat)" => The fat cat sat on the mat.

           后发正(?<=exp) 匹配(fat|mat)前面跟 T/t he 空格 s

          "(?<=(T|t)hes)(fat|mat)" => The fat cat sat on the mat.

        后发负(?<!exp) 匹配 cat 前面不跟 T/ t he 空格 s

          "(?<!(T|t)hes)(cat)" => The cat sat on cat.

    (5)分组与捕获、引用(匹配模式)与反向引用(匹配值)

       1.分组与捕获(捕获元与非捕获元)。

        分组是用圆括号“()”括起来的正则表达式,匹配出的内容就表示一个分组。使用 | 元字符来表示分组,| 的两侧是两个分组。

         例如, exp1 | exp2 表示两个分组,在严格意义闪给,不认为由  |  构成的正则表达式是分组。

        分组和捕获在正则表达式中有着密切的联系,一般情况下,分组即捕获,都用小括号完成:   

          (exp)    分组,并捕获该分组匹配到的文本 即捕获元(引用型)

          (?P<name>exp) :分组并定义分组命名,为捕获元(引用型),可以使用 和 别名name 引用

          (?:exp)  分组,但不捕获该分组匹配到的文本 即非捕获元(非引用型),

        还有两个非捕获元是 ?= 和 ?!,

        前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串。

        后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。

        什么是捕获呢?使用小括号指定一个子表达式后,子表达式匹配的文本(即匹配的内容)可以在其他子表达式中被引用。

        2.引用型(捕获元)分组的引用与反向引用(键匹配与值匹配)。

       (1)分组编号的引用

        以 左( 为标志,从1开始,下面以(A(B(C))) 示例:

          /1 (A)

          /2 (B(C))

          /3 (C)

       (2)分组命名的引用

         re.search(r"(?P<dog>ab)cdef",'abcdefghti').group('dog')

         Out[130]: 'ab'

   python的re模块,可以把(?P<name> exp),即将 (ab)子式命名为dog,组引用不用编号引用 1,dog别名引用即可。

    (3)捕获元分组的引用和反向引用

      捕获元(引用型)分组即(exp)的引用,无论是编号引用还是别名引用,都是键引用,即引用的是分组表达式,而非匹配到的字符串值。

      而反向引用即是值引用,即引用的是分组的表达式正则具体匹配到的值,而非未明确匹配内容的匹配模式(分组表达式)。

      下面是反向引用的一个典型示例:显然 1引用的是值匹配,am,而不是 w+。

        寻找重复单词,定义正则表达式,该正则表达式表示两个相同的单词顺序出现:

              (w+)s+1

              

            注意,该正则表达式并不等价于:(w+)s+(w+),该表达式表示两个单词是相邻的:

              

      3.非捕获元(非引用型)分组,即(?:exp)无法被引用

      只能在当前的位置匹配文本,正则表达式不为该分组自动分配组号。

       例如,正则表达式:(?:w+)s+1 是错误的,因为无捕获分组不占用组号, 

       而正则表达式 (?:w+)?(w+)s+1 是正确的,第二个分组的组号是1,1引用的是第二个分组。

    (6)标志 / 模式修正符

      i 忽略大小写(Case Insensitive)

      g 全局搜索(Global search)

        修饰符 g 常用于执行一个全局搜索匹配,即(不仅仅返回第一个匹配的,而是返回全部)。

        例如,表达式 /.(at)/g 表示搜索 任意字符(除了换行)+ at,并返回全部结果。

          "/.(at)/" => The fat cat sat on the mat.

          "/.(at)/g" => The fat cat sat on the mat.

      m 多行修饰符(Multiline)

      多行修饰符 m 常用于执行一个多行匹配。

   像之前介绍的 (^,$) 用于检查格式是否是在待检测字符串的开头或结尾。但我们如果想要它在每行的开头和结尾生效,我们需要用到多行修饰符 m

   例如,表达式 /at(.)?$/gm 表示小写字符 a 后跟小写字符 t ,末尾可选除换行符外任意字符。根据 m 修饰符,现在表达式匹配每行的结尾。

           "/.at(.)?$/" =>   The fat

                     cat sat

                   on the mat.

          "/.at(.)?$/gm" => The fat

                  cat sat

                  on the mat.

   y y修饰符规定正则表达式必须从lastIndex规定的位置开始进行匹配。

     也就是说,如果开始匹配的位置不是从lastIndex规定位置开始,匹配失败,不再继续尝试。

   u u 修饰符标识能够正确处理大于uFFFF的Unicode字符。

        也就是说,会正确处理四个字节的UTF-16编码。

    (7)(贪婪)最大长度匹配与(非贪婪)最小长度匹配

      正则表达式默认采用贪婪匹配模式,在该模式下意味着会匹配尽可能长的子串。

      我们可以使用 限定符加上 ? 将贪婪匹配模式转化为惰性匹配模式。

      即 *?   +?   ??    {n,}?   {n,m}?

        "/(.*at)/" => The fat cat sat on the mat.

        "/(.*?at)/" => The fat cat sat on the mat.

    

参考教程地址:

  菜鸟教程:https://www.runoob.com/regexp/regexp-tutorial.html

  github learn-regex:  https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md

  蚂蚁部落:http://www.softwhy.com/qiduan/regex_source/

  悦光阴 博客园 :https://www.cnblogs.com/ljhdo/p/10678281.html

  regex在线练习地址:https://regex101.com/

    

原文地址:https://www.cnblogs.com/liuchaodada/p/12070500.html