Python-30-正则表达式

正则表达式

  1. 处理对象:字符串,python中使用re模块

  2. 语法规则

     *   匹配0次或多次
     +   匹配1次或多次
     ?   匹配0次或1次
     \   转义字符,使字符改变原来的意思
     ^   匹配字符串开头
     $   匹配字符串结尾
     |   或,匹配|左右表达式任意一个,从左到右匹配,如果|没有包括在()中,则它的范围是整个正则表达式
     {}  {m}匹配前一个字符m次,{m,n}匹配前一个字符m至n次,{m,}匹配m至无限次
     []  字符集,多选一,对应的位置可以是字符集中任意字符分组表达式作为一个整体,可以后接数量词。
         [a-z]从a到c   [0-9] 0-9的数字   [09-] 0、9、-三个字符  [0\-9] 0、9、-三个字符
     ()  被括起来的表达式将作为分组,从表达式左边开始没遇到一个分组的左括号“(”,编号+1。分组表达式作为一个整体,可以后接数量词。表达式中的|仅在该组中有效。
    
  3. 预定义字符集

     \d  数字[0-9]
     \D  非数字[^\d]
     \s  匹配任何空白字符[<空格>\t\r\n\f\v]
     \S  非空白字符[^\s]
     \w  匹配包括下划线在内的任何字字符[A-Z a-z 0-9 _]
     \W  匹配非字母字符,即匹配特殊字符
     \A  仅匹配字符串开头,同 ^
     \Z  仅匹配字符串结尾,同 $
     \b  匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置
     \B  [^\b]
     . 匹配除换行符 \n 外的字符
    
  4. 特殊分组用法

     (?P<name>str)  分组,除了原有的编号外再指定一个额外的别名  (?P<id>abc){2}  abcabc
     (?P=name)      引用别名为<name>的分组匹配到字符串     (?P<id>\d)abc(?P=id) 1abc1  5abc5
     \<number>      引用编号为<number>的分组匹配到字符串   (\d)abc\1   1abc1 5abc5
    
  5. 例子

    • 字符 \d 的理解

         import re
         regex = re.compile(r'\d+')
         s = 'abc123adawae12edqwe657'
         res = re.findall(regex, s)
         print(res)  # ['123', '12', '657']
      
    • 字符 \b 的理解

        import re
        regex1 = r'\btina'
        res1 = re.findall(regex1, 'tiantinaaaa')
        print(res1)  # []
        regex2 = r'\btina'
        res2 = re.findall(regex2 ,'tian tinaaaa')
        print(res2)  # ['tina']
        regex3 = r'\btina'
        res3 = re.findall(regex3, 'tian#tinaaaa')
        print(res3)  # ['tina']
        regex4 = r'\btina\b'
        res4 = re.findall(regex4, 'tian#tina@aaa')
        print(res4)  # ['tina']
      
    • 字符集[]的理解

         import re
         name = '李小明'
         regex = re.compile(r'李[二小]明')
         res = re.match(regex, name)
         print(res)  # <re.Match object; span=(0, 3), match='李小明'>
      
    • 或|的理解

         import re
         name = '李小明'
         regex2 = r'李(二|小)明'
         res = re.match(regex2, name)
         print(res)  # <re.Match object; span=(0, 3), match='李小明'>,若去掉(),为None
      
    • 字符\s的理解

         import re
         s='''
             <name id="001">
                 tom
             </name>
             <age>12</age>
             <name>jack</name>
             <name id='002'>rose</name>
         
         '''
         regex5 =r'<name id=.+>\s*(\w+)\s*</name>'
         res5 = re.findall(regex5, s)
         print(res5)  # ['tom', 'rose']
      
    • 匹配电话号3/4位(0+2/3位)+(7/8位)

         import re
         s6 = '0112-12345678'
         regex6 = re.compile(r'0\d{2,3}-\d{7,8}')
         res6 = re.match(regex6, s6)
         print(res6)  # <re.Match object; span=(0, 13), match='0112-12345678'>
      
    • 匹配邮箱 字符@字符.2/3.2/3

         import re
         s7 = '11368218@qq.com'
         regex7 = re.compile(r'\w+@\w+(\.\w{2,3}){1,2}')
         res7 = re.match(regex7, s7)
         print(res7)  # <re.Match object; span=(0, 15), match='11368218@qq.com'>
      
    • 不获取?:的使用

         # 当不加括号(),全部都要--findall
         # ()分组,只保留括号内的--findall
         # (?: ) 当表示分隔符,不是分组内容,即不获取,则加上 ?:
         import re
         # regex8 = re.compile(r'\w+@\w+(\.\w{2,3}){1,2}')
         regex8 = re.compile(r'(\w+@\w+(?:\.\w{2,3}){1,2})')
         s8 = 'abac@163.com.cn fdkfjd lzhan@qq.com,fdkjfkdfjdk,aaa@qq.cjom'
         res8 = re.findall(regex8,s8)
         print(res8)  # ['abac@163.com.cn', 'lzhan@qq.com', 'aaa@qq.cjo']
      
    • 对 ^ $ 的理解

         regex9 = re.compile(r'^李\w{1,2}$')
         # regex9 = re.compile(r'李\w{1,2}')
         #如果不加上开始和结束标志,其实就是匹配部分数据,下面的字符串就会匹配'李小飞'
         s9 = '李小飞龙'
         res9 = re.findall(regex9, s9)
         print(res9)  # []
      
    • 查找不存在某字符串的

        s1 = '123dsifd'
        s2 = '123abc2312'
        import re
        regex = r'(?!.*abc).*'
        res1 = re.match(regex, s1)
        print(res1)  # <re.Match object; span=(0, 8), match='123dsifd'>
        res2 = re.match(regex, s2)
        print(res2)  # None
      
  6. 完全匹配

     ^\w{3}\w{3}$  完全匹配  整个字符与整个规则进行匹配--与match结合用
    
  7. 规律匹配

    1. 匹配abcabc类型

       print('【匹配abcabc类型】:')
       import re
       s1='abcabc'
       s2='abcdef'
       reg01 = r'^(?P<fir>\w+)(?P=fir)$'
       res1 = re.match(reg01, s1)
       res2 = re.match(reg01, s2)
       print(res1)  # <re.Match object; span=(0, 6), match='abcabc'>
       print(res2)  # None
      
  8. re模块中常用的功能函数

    1. compile():将正则表达式编译成Python识别的语句

       import re
       s1='abcabc'
       s2='abcdef'
       reg01 = r'^(?P<fir>\w+)(?P=fir)$'
       regex  = re.compile(reg01)
       res1 = re.match(regex, s1)
       res2 = re.match(regex, s2)
       print(res1)  # <re.Match object; span=(0, 6), match='abcabc'>
       print(res2)  # None
      

      flags = re.I 忽视大小写
      flags = re.S 使.匹配包括换行在内的所有字符
      flags = re.L 做本地化识别(locale-aware)匹配,法语等
      flags = re.M 多行匹配,影响^和$
      flags = re.X 通过给予更灵活的格式以便将正则表达式写得更易于理解
      flags = re.U 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B

       import re
       s = 'abc ABC'
       regex = re.compile(r'abc', flags=re.I)
       res = re.findall(regex, s)
       print(res)  # ['abc', 'ABC']
      
    2. match():匹配,不是完全匹配

      决定re是否在字符串刚开始的位置匹配。//注:这个方法并不是完全匹配。

      当pattern结束时若string还有剩余字符,

      仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符’$’

      没有()就是匹配模式,匹配模式就是从开始第一个字符进行匹配,如果匹配成功,那么后面的内容就不会匹配。

      有了()就是分组查找模式,有了分组就是把匹配到的内容分组存放

    3. search():查找,在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。

    4. findall():遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表。

       import re
       s = 'abc 中国 Anb 深圳 dsjkfjk 日本asf'
       regex = re.compile(r'[\u4E00-\u9FA5]+')
       res = re.findall(regex, s)
       print(res)  # ['中国', '深圳', '日本']
      
    5. finditer(): 搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器

      找到 RE 匹配的所有子串,并把它们作为一个迭代器返回。

       import re
       iter = re.finditer(re.compile(r'\d+'), 'jhdsafh12hdfsf34?56')
       for i in iter:
           print(i)  # 迭代器 <re.Match object; span=(7, 9), match='12'>
           print(i.group())  # 值 12
           print(i.span())  # 下标 (7,9)
      
    6. split():此处为正则表达式中的分割

       import re
       time = '2019-2-30 16:20:00'
       regex = re.compile(r'[- :]')
       res = re.split(regex,time)
       print(res)  # ['2019', '2', '30', '16', '20', '00']
      
    7. sub():替换

       import re
       time = '2019-2-30 16:20:00'
       regex = re.compile(r'[- :]')
       res = re.sub(regex, ',', time)
       print(res)  # 2019,2,30,16,20,00
      
  9. 贪婪匹配和非贪婪匹配

     # 贪婪匹配
     import re
     s='lookandlook'
     regex = re.compile(r'l\w*k')
     res = re.findall(regex, s)
     print('贪婪模式:',res)  # 贪婪模式: ['lookandlook']
     
     # 非贪婪匹配:*?  +?  ??  {m,n}?
     import re
     s='lookandlook'
     regex = re.compile(r'l\w*?k')
     res = re.findall(regex, s)
     print('非贪婪模式:',res)  # 非贪婪模式: ['look', 'look']
     
     s21 = '<H1>title</H1>'
     regex21 =  re.compile(r'<.*>')
     res21 = re.match(regex21, s21)
     print(res21)  # <re.Match object; span=(0, 14), match='<H1>title</H1>'>
     regex22 = re.compile(r'<.*?>')
     res22 = re.match(regex22, s21)
     print(res22)  # <re.Match object; span=(0, 4), match='<H1>'>
    
  10. re.match与re.search与re.findall的区别

    re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None

    re.search匹配整个字符串,直到找到一个匹配。

    re.findall查找所有匹配的

    a = re.search('[\d]', "abc33").group()
    print(a)  # 3
    p = re.match('[\d]', "abc33")
    print(p)  # None
    b = re.findall('[\d]', "abc33")
    print(b)  # ['3', '3']
    
  11. 简单爬虫

    import re
    sss = '''
        <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>Title</title>
            </head>
            <body>
                <li>001</li>
                <li>002</li>
                <li>003</li>
                <li>004</li>
            </body>
            </html>
    '''
    regex_sss = re.compile(r'<li>(.+?)</li>')
    res_sss = re.findall(regex_sss, sss)
    print(res_sss)
    
上一篇:Python爬虫实战之爬取百度贴吧帖子


下一篇:vue经典面试题两问