re 模块===正则表达式

时间:2022-12-15 16:01:04

所有的模块要经历的两个步骤:

    要操作的概念本身:   正则表达式    时间  等

    使用模块去操作它:   re                    time

re  模块

正则表达式

  基础知识

    什么是正则表达式?

      一种匹配字符串的规则

    正则表达式能做什么?

      可以定制一个规则:

        1. 来确认某一个字符串是否复合规则

        2.  从大段字符串中找到复合规则的内容

      程序领域:

        1.  登录注册页的表单验证   

          如  手机号的格式判断

        2  爬虫

          把网页下载下来, 从里边提取一些信息, 找到我要的所有信息,  做数据分析

        3.  自动化开发      日志分析

      明确一件事:

        正则表达式   是一种独立的语法

        和python没有关系

   正则表达式         元字符+量词

      元字符

        字符组   [  ]   [  ^ ]        个性化定制,

                  下面这一组无法描述的一般用上面的字符组的形式

          [ ]   在一个字符位置上能出现的内容 ,  之约束一个位置

                [\d\s]一个特殊元字符无法描述一个字符出现的内容了

              e.g     这个范围是根据  ASCII码中的大小顺序来说的

                 [ 1bc ]   表示这个位置上  1, b, c  都可以放

                [ 0-9 ]   表示 这个位置上  可以是  1 到 9 的任意数字

                    不能是  9-0  因为  范围只能是  从小到大

                [ a-z ]   表示这个位置上  只能是  小写 的  26 个英文字母

                    不能是   z-a  范围也只能是  从小到大

                [ A-Z ]   表示这个位置上  只能是  大写的  26 个英文字母

                    不能是   Z到a A  范围也只能是  从小到大

                [ 0-9 ] [ a-z ] [ A-Z ]  这样表示  约束的是三个字符  

                        顺序必须是   数字  小写字母   大写字母

                [ 0-9 a-z A-Z ] 表示一个字符  上  数字字母都可以

 

          [  ^    ]      表示非 ^后边的字符  这个格式可以放到任何位置

              e.g    

                [ ^ abc ]    表示这个字符上   非 a  非b   非c    

          |    ()

             |      表示 或者     左边或者右边

            ( )    表示分组    可以对括号中的一组进行  统一的量词的使用

              

        \w  \d  \s( \n  \t  )      \W   \D    \S  

          \w  == [0-9a-zA-Z_]    表示匹配  数字字母下划线  都可以

          \d == [0-9]    表示  匹配一个数字

          \s  ==[ \n \t   ]    表示  任意空白符  包括  空格 回车  制表符 tab 

          \n  表示只匹配 回车换行

          \t   表示 之匹配  制表符

          \W  表示  匹配  非数字字符下划线

          \D   表示  匹配  非数字

          \S 表示匹配  非空白 

         [\d\D]  [\w\W]  [\s\S]   都可以表示 匹配所有 

        ^    $    .   

          ^  表示  以什么开头  

            $  表示   以什么结尾  

          .   表示除了 \n 换行符外的任意字符    爬虫容易用    但是表单验证不容易用

      量词

        ?   +   *  

          ?    表示  重复   0  次   或   1 次

          +   表示    重复    1次   到   无穷多次

          *     表示  重复     0次   到    无穷多次    

        { n }     { n , }   { n , m } 

          { n }  表示  重复  n  次

          { n , }  表示  至少重复n 次       贪婪匹配    尽可能多的去匹配       采用的是回溯算法    

          { n , m }   表示重复 n 到 m 次    

      特殊的用法和现象

        ? 的使用

          1.   在量词后边 跟一个?  表示  取消  贪婪匹配    非贪婪       找复合条件的但是最短的           

              ??     *?   +?    { n }?

              .*?x  最常用    表示  匹配任意字符直到找到一个x       

在python中使用正则表达式

    转义符:

        \n  里边的    \  转义符  赋予了这个n一个特殊的意义,     表示换行符

        若想打印出来 \n  必须要在他前边 再加一个 \   也就是说   \\n  才表示打印出来的 \n形式

          因此    当你看到这个  \  的时候不应该理解为 这是一个 \  ,  它是一个转义符   

            你要是想把这个转义符变为一个字符串  \ ,  它必须经过转义

              而   \\   就等于是 字符串数据类型的  \ 

         如果一个字符串类型的\ 取消了 它转义符的意思 , 就表示  一个字符串

         那么就不需要 再使用  \\ 来表示  \  了

         我们就在字符串前面 加上一个  r '  '  ,  取消这个字符串中所有  \  的转义 

            e.g     import  re

               ret = re . search( '' \\\\n ''  , ''  \\n '' )

               print(ret.group())   ===>  \

               ret = re . search( r'' \\n ''  ,r ''  \n '' )     #  前边加上r 就相当于取消了 转义  全是按照原来的 来匹配的

               print(ret.group())   ===>  \n

         在测试工具中  ,  如果带了 \  , 你有担心 他会出现转义的情况  

          不管三七二十一  ,   在测试工具中 里测好了代码

            拿到  python 中 , 统一  放在 字符串 r '  '  引号中  就行了

          

    re模块

      常用的方法    相当于字符串的  匹配

        import  re

 

        findall  *****         一般在  获取所有 匹配项的时候用   因为结果是  匹配项组成的一个 列表

            语法      ret   =  re. findall( ' 正则表达式 ' , ' 要匹配的字符串 ' )

            返回值      print( ret )  是一个列表  其中的元素是 符合正则的 每一个结果   [ ' ' , ' ' , ' ' ]

               若没符合正则的 结果   则返回值为   空列表   [  ]  

            返回值个数   :  只有一个  列表 或 空列表 

           e.g    import  re

               ret = re.findall( ' \d+ ' , ' 1457jhuuh5866' )

               print( ret )   ===>   [  ' 1457 '   ,   '  5866 ' ]

                 ret = re.findall( ' \d+ ' , ' jkugjhuuh' )

              print( ret )  ===>     [  ] 

 

        search  *****    一般在取 匹配项的   第一个 值的时候用

            语法      ret = re . search( ' 正则表达式 '  , ' 要匹配的字符串 ' ) 

                print( ret )   ===>  <_sre.SRE_Match object; span=(0, 5), match='18575'>
                print(  type(ret)  )  ===>   <class '_sre.SRE_Match'>  

                print( ret.group() )   ===>   将符合正则的  第一项  拿出来    

            返回值     是符合正则结果的 对象  

            返回值个数   1    

            若没有符合正则的 项    则返回类型 为    None Type  

              因此   一般会这样写     if  ret  :   print( ret.group() )   

                     当符合正则的时候才打印   否则不打印  结果就为空  不会报错

          e.g    

            ret = re.search( ' \d+ ' , ' 1457jhuuh5866' )

            if  ret  :       print( ret .group())             ===>            1457  

            ret = re.search( ' \d+ ' , ' jkugjhuuh' )

               print( ret )  ===>   NoneType 

              if   ret :     print( ret.group()  )     ====>       啥都没有

        match  **    不管正则表达式写成什么  都相当于 前边加了一个   ' ^ 正则 '  ,  

            就相当于  是判断  是否 以正则条件  开始的    无论是或否结果都是  一个返回值

             语法   ret = re.match(  ' 正则表达式 '   ,   ' 要匹配的字符串 '  ) 

                print( ret )  ===>    None    或者    <_sre.SRE_Match object; span=(0, 4), match='5856'>

             返回值   print( ret.group() )     ===>   匹配对象    或  报错  NoneType

           e.g    ret = re.match( ' \d+ ' , ' 1457jhuuh5866' )

               print( ret.group())  ====>    1457       

               ret = re.match( ' \d+ ' , ' jhuuh5866' )

               print( ret.group())  ====>   None

 

        替换  ***       相当于  replace 

          sub ***      返回  一个 替换后的 结果       若没有替换则返回 原来的字符串

            语法     ret =re.sub(  ' 正则表达式 '   ,  ' 要替换的结果 '  ,  ' 要匹配的字符串'  ,   要替换的数量  )

            返回值    print( ret ) ===>      替换的那个结果      若没换就是原来的 字符串

          subn ***     返回 一个 元组形式  (  '' 结果  ''  ,     0 / 匹配的次数   )

            语法     ret =re.sub(  ' 正则表达式 '   ,  ' 要替换的结果 '  ,  ' 要匹配的字符串'  ,   要替换的数量  )

            返回值   print( ret ) ===>        (  ''  结果 ''  ,   替换的次数  )       若没有替换  次数则为 0  

           e.g  ret = re.sub( ' \d+ ' , ' H ' , ' 1457jhuuh5866' )

             print(ret)  ===>    HHHHjhuuhHHHH

              ret = re.subn( ' \d+ ' , ' 1457jhuuh5866' )

             print( ret )  ===>   ( ' HHHHjhuuhHHHH'  ,  8  )

        切割***

          split***   返回的是切割后的列表      若没有符合正则的  则是一个列表中  是  原来的字符串  列表

            语法    ret = re.split( ' 正则表达式 '  , ''  要切割的 字符串 '' )

            返回值   print( ret )  ==>   [ '' '' , '' '' , '' '' ]    或   [ ' 原来字符串 ' ]

           e.g   ret = re.split( '' \d+ '' , ' alex83taibai85 ' )

             print( ret ) ===>   [ '' alex '' , '' taibai '' , '' '' ]   #因为最后是一个数字  所以列表最后 是一个空字符

        进阶方法   *****  爬虫\ 自动化开发

          compile  *****      提高时间效率         节省时间  

            在  findall  中  是先将正则表达式  变成  pyhon能理解的 代码  ,  然后  再去  执行代码  

            若只用一次  ,  不节省时间

            只有在多次使用某一个 相同的正则表达式 的时候  这个  compile 才会帮助我们 提高程序的效率     节省时间

              语法   ret  = re.compile( '' 正则表达式 '' )

                 ret1 = ret.search( '' 要匹配的字符串 '' )

              返回值  print( ret1.group() )    拿到  第一个  符合  正则的  匹配对象

                若无匹配项   则返回  None 

               e.g    ret = re.compile( ' 负数的正则表达式 '' )

               ret1 = ret.search( '' jgrugh-5gjeeg9-41bg '' )

               print( ret1.group() )    ===>   -5

               ret2 = ret.search( ''  jguheufhe  '' ) 

               print(ret2)  ===>   None  报错

          finditer  *****       提高空间效率        节省内存

            findall 是将 符合正则的匹配项  全部放到 一个列表中   太占内存

              而  finditer  是将列表变为一个  迭代器  可以  一个一个拿   节省内存

            语法   ret = re.finditer( '' 正则表达式 '' ,  '' 要匹配的字符串  ''  )

                 for  r  in  ret  :      

                  print( r.group() )     #    拿到  每一个值   

              e.g     ret = re . finditer( '' 负数的正则表达式 '' , '' gjgj-85hfgf-58yfy85 '' )

                 for  r in  ret:

                    print(r.group())   ===>     -85     -58  

    python中的正则表达式

     在正则表达式中   遇见分组  的特殊 方法  

          findall     会优先显示分组中的内容  ,  要想取消分组优先  则  (?:正则表达式)    

              e.g   ret=re.findall(r'\d+(?:\.\d+)|(\d+)','1-2*(60+(-40.35/5)-(-4*3))')  

                    正则表达式  :   前边是 小数的表达式  |  整数的表达式       表示 小数或整数都可以

                          但是   后边 整数表达式 用分组括起来了    表示  优先显示分组中的  整数

                          即便是有小数也不让其显示出来,   

                        因此  匹配项是  数字  但是小数没有显示出来     所以就是 一个空的字符

                  print(ret)  ===>    [ '1', '2', '60', ' ', '5', '4', '3']  

                  ret.remove(" ")     将列表中的空格字符删去

                  print( ret )   ===>    [ '1', '2', '60', '5', '4', '3']    得到最后的结果

          split         遇到分组会保留分组内被 切掉的内容

            e.g    

          search     如果  search 中有分组的话  ,  通过 group(n)  就能拿到  group中的 匹配项的内容

                        即  可以拿到   n  对应的第n个分组中的  匹配项

            e.g    ret = re.search( '' \d+(.\d+)(.\d+)(.\d+)? '' ,  '' 1.2.3.4-2*(60+(-40.35/5)-(-4*3)) ''  )

                print(ret.group())    ===>     1.2.3.4       #  匹配项

              print(ret.group( 0 ))   ===>     1.2.3.4

              print(ret.group( 1 ))   ===>      .2     #  对应第n个分组 中的  匹配项 

              print(ret.group( 2 ))   ====>    .3

              print(ret.group( 3 ))   ====>    .4

      分组命名

        我们可以通过  对 分组命名将  分组中的匹配项匹配出来

          方法一 :   方便常用

          (  ?P< 名字name > 正则表达式  ) 再再后边使用 同分组内容的的时候

                可以  ( ?P=名字name )  表示和前边同名分组内容一摸一样的  分组内容

             显示分组中内容的时候可以   print(ret.group( '' 名字name '' ))

          方法二 :    不推荐经常用的

          ( 正则表达式 )     再使用   这个分组的时候   可以 用   \ n   来表示   n表示  第几个分组

                内容也是一模一样才可以

              显示分组中的内容的时候   print(ret.group( n ))   

        e.g  

          ret = re.search (    '' < (?P<name>\w+)>\w+</(?P=name)> ''    ,     ''  <h1>hello<h1> ''    )

          print(ret.group('name'))   #  得到 分组name中的匹配项       h1

          print( ret.group() )     #   得到结果   <h1>hello<h1>

 

          ret = re.search (    '' < (\w+)>\w+</  \ 1 > ''    ,     ''  <h1>hello<h1> ''    )

          print(ret.group(1))   #  得到 第一个 分组中的匹配项       h1    

          print( ret.group() )     #   得到结果   <h1>hello<h1>

        当然  也可以对不同的组分别命名  ,  从而得到  各个分组中的  匹配项

 

       

import  random  模块

  随机  :  在某个范围内取到的每一个值得概率相同

    随机小数   

      语法   :  print( random.random() )      0 到 1 内的随机小数

          print( random.uniform( n , m  ) )    n到m  之内的任意小数

    随机整数

       语法    print( random.randint( n , m ) )       [ n , m ]   之间的随机整数   闭区间

          print( randon.randrange( n , m ) )    [ n , m )   之间的随机整数    不带 m

          print( random.randrange( n, m, a) )  [ n , m)    之间  每a 个找一个的随机整数     

    随机抽取

        lst= [    ...  ] 

        ret = random.choice( lst )

         print( ret )     随机抽取一个值

        ret = random.sample( lst , n)

        print( ret )   随机抽取n个

       打乱顺序

        random.shuffle( lst )

        print( lst )   在原列表上 打乱 lst 的 顺序

    抽奖 \ 彩票\ 发红包\验证码 

      e.g  4位验证码 数字

          def   rand_code( n=4 ) :

            code = ''  ''

            for  i  in  range( n ):

              num = random.randint( 0 , 9 )

              code = code + str( num )

            return  code 

          print( rand_code() )   #   默认调用 函数   得到  四位的  数字验证码

          print( rand_code( 6 ) )   #   传个参数  得到  参数位的  数字验证码

      e.g     数字 / 字母 验证码  6  位  

        def  rand_code( n=6 , als = True ) :     

          code = ''  '' 

          for  i  in  range ( n ) :

            rand_int =str( random.randint( 0 , 9 ))    

            if  als :    #   当 als  为  False  时  不执行   只能得到  数字的验证码

              rand_alp = chr (random.randint( 97 , 122 ))

              rand_alo = chr (random.randint( 65, 90 ))

              rand_int = random.choice( [ rand_alp , rand_int , rand_alo ] )

            code = code+rand_int 

          return code

        ret = rand_code( n = 4 )    传参数  可以得到  任意位的验证码

        print( ret )