美文网首页
Python / re 正则表达式

Python / re 正则表达式

作者: 书写不简单 | 来源:发表于2018-11-22 15:43 被阅读0次

    Python中经常会用到正则表达式来筛选数据,这里列举一些常用的正则方法仅供参考

    先来看一下匹配规则:


    常用的匹配规则.jpeg

    其实正则表达式不是Python独有的,在其他的编程语言中也可以使用。但是Python的 re 库提供了整个正则表达式的实现,利用这个库,就可以在Python中使用正则表达式。

    常用的方法

    match()

    match() 方法会尝试从字符串的开头匹配字符串,如果匹配成功,就返回结果;如果匹配失败,就返回None ,示例如下:

    import re
    
    content = "Hello 987 1233 My name is Kings"
    print(len(content))
    
    # 匹配
    result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{2}', content)
    print(result)
    print(result.group())
    print(result.span())
    

    结果如下:

    31
    <_sre.SRE_Match object; span=(0, 17), match='Hello 987 1233 My'>
    Hello 987 1233 My
    (0, 17)
    

    说明:

    1. 这里面用到的匹配模式有 \s : 匹配任意的空白字符 ; \d :匹配任意数字 ;\w:匹配任意的字母、数字、下划线;{n} :匹配 n 个前面的表达式;
    2. match() 方法中,第一个单数传入正则表达式,第二个参数传入要匹配的字符串
    3. group() 方法可以输出匹配到的内容
    4. span() 方法 可以获取到匹配的长度

    上面就是用match() 方法来匹配一段文字。但是工作中经常不用这种方式,都是匹配一部分内容,该怎么匹配呢?

    • 匹配目标

    我们使用正则去匹配内容,怎么提取到我们想要的结果呢?这里我们可以使用()来将我们要提取的部分给括起来,然后调用 group() 方法即可。
    示例如下:

    import re
    
    content = "Hello 9871233 My name is Kings"
    print(len(content))
    
    # 匹配
    result = re.match('^Hello.*(\d+).*s$', content)
    print(result)
    print(result.group(1))
    print(result.span())
    

    结果如下:

    30
    <_sre.SRE_Match object; span=(0, 30), match='Hello 9871233 My name is Kings'>
    3
    (0, 30)
    

    说明:

    1. 使用group(n):可以提取第 n 个被()包含的内容
    2. 如果使用 group() : 获取的是整个内容
    • 通用匹配

    从上面的例子中我们可以看出,出现数字的地方用了好多\d,有空白我们就用 \s,如果数字和空白很多的话,这种方式就是不可取的了。。这里有一个通用的匹配:就是 .(点星)。.(点)可以代表任何除换行符之外的字符,(星)可以代表前面0个或多个表达式。二者组合,就可以
    示例如下:

    import re
    
    content = "Hello 987 1233 My name is Kings"
    print(len(content))
    
    # 匹配
    result = re.match('^Hello.*s$', content)
    print(result)
    print(result.group())
    print(result.span())
    

    结果如下:

    31
    <_sre.SRE_Match object; span=(0, 31), match='Hello 987 1233 My name is Kings'>
    Hello 987 1233 My name is Kings
    (0, 31)
    

    说明:

    1. 使用 匹配模式 $:表示匹配一行字符串的结尾
    • 贪婪与非贪婪

    使用上述的通用匹配模式有可能提取不到我们想要的结果。看下面的例子:我们想要提取所有的数字!

    import re
    
    content = "Hello 9871233 My name is Kings"
    print(len(content))
    
    # 匹配
    result = re.match('^Hello.*(\d+).*s$', content)
    print(result)
    print(result.group(1))
    print(result.span())
    

    结果如下:

    30
    <_sre.SRE_Match object; span=(0, 30), match='Hello 9871233 My name is Kings'>
    3 (结果就一个数字,而不是一串数字)
    (0, 30)
    

    看到结果只有一个数字。。。这是为什么?这里就提到了 贪婪匹配 、非贪婪匹配。
    贪婪匹配:.* (点星)尽可能多的匹配字符串
    非贪婪匹配:.*? (点星问好)尽可能少的匹配字符串

    我们现在把 ?(问好) 加进去,看看会发生什么:

    import re
    
    content = "Hello 9871233 My name is Kings"
    print(len(content))
    
    # 匹配
    result = re.match('^Hello.*?(\d+).*s$', content)
    print(result)
    print(result.group(1))
    print(result.span())
    

    结果如下:

    30
    <_sre.SRE_Match object; span=(0, 30), match='Hello 9871233 My name is Kings'>
    9871233
    (0, 30)
    

    现在的结果就是我们要想要的了。
    说明:

    1. 如果我们想提取的内容在字符串的结尾,那么我们就不能使用 非贪婪模式了,因为它是尽可能少的获取内容。如果使用,我们可能获取不到结果。
      实例如下:
    import re
    
    content = "Hello 9871233 My name is Kings"
    print(len(content))
    
    # 匹配
    result = re.match('^Hello.*?(\d+).*is\s(.*?)', content)
    print(result)
    print(result.group(2))
    print(result.span())
    

    结果如下:

    30
    <_sre.SRE_Match object; span=(0, 25), match='Hello 9871233 My name is '>
    结果为空
    (0, 25)
    
    • 修饰符

    修饰符有很多,这里只介绍两种,在网页匹配中经常用到的。re.Sre.I
    re.S : 解决换行匹配问题
    re.I :解决大小写问题
    示例如下:re.S

    import re
    
    content = '''Hello 9871233 My name 
    is Kings'''
    print(len(content))
    
    # 匹配
    result = re.match('^Hello.*?(\d+).*is(.*)', content, re.S)
    print(result)
    print(result.group(2))
    print(result.span())
    

    结果如下:

    31
    <_sre.SRE_Match object; span=(0, 31), match='Hello 9871233 My name \nis Kings'>
     Kings
    (0, 31)
    

    示例如下:re.I

    import re
    content = '''Hello 9871233 My name is Kings'''
    print(len(content))
    
    # 匹配
    # 来个大写字母 O
    result = re.match('^HellO.*?(\d+).*is(.*)', content, re.I)
    print(result)
    print(result.group(2))
    print(result.span())
    

    结果如下:

    30
    <_sre.SRE_Match object; span=(0, 30), match='Hello 9871233 My name is Kings'>
     Kings
    (0, 30)
    
    • 转义匹配

    前面介绍了好多匹配模式,但是,如果目标字符串里面包含匹配模式对应的字符,又该怎么办呢?
    这就用到了 转义字符:当遇到特殊字符(正则匹配模式字符)时,在前面加反斜杠\ 转义就行。
    实例如下:

    import re
    
    content = '(百度)www.wangpai.com?order=123&name=xiaoerlang'
    print(len(content))
    
    # 匹配
    result = re.match('^\(百度\)www\.wangpai\.com\?order=(.*?)&name=(.*)', content, re.S)
    print(result)
    print(result.group(1))
    print(result.group(2))
    

    结果如下:

    45
    <_sre.SRE_Match object; span=(0, 45), match='(百度)www.wangpai.com?order=123&name=xiaoerlang'>
    123
    xiaoerlang
    

    search()

    前面我们提到了 match() 方法,只能从字符串开头匹配,如果不从字符串开头匹配怎么办呢?
    search() 方法:它会扫描整个字符串,然后返回第一个成功匹配的结果。如果没有找到结果,就返回None。
    示例如下:

    import re
    
    
    html = '''
    <div class="pc_temp_songlist  pc_rank_songlist_short">
                            <ul>
                                                            <li class=" " title="冷漠、李磊 - 我们想要的" data-index="12">
                                    <span class="pc_temp_btn_check pc_temp_btn_checked" data-index="12"></span>
                                    <span class="pc_temp_coverlayer"></span>
                                    <span class="pc_temp_num">
                                                                                                                13
                                                                        </span>
                                                                    <span class="pc_temp_tips_l">
                                        <i class="pc_temp_icon_new" title="新入榜"></i>
                                    </span>
                                                                    <a href="http://www.kugou.com/song/pyaswf9.html" data-active="playDwn" data-index="12" class="pc_temp_songname" title="冷漠、李磊 - 我们想要的" hidefocus="true">冷漠、李磊 - 我们想要的</a>
                                    <span class="pc_temp_tips_r">
                                                                            <a href="javascript:;" data-active="play" data-index="12" class="pc_temp_btn_listen" title="播放" hidefocus="true">播放</a>
                                        <a href="javascript:;" onclick="_hmt.push(['_trackEvent', 'hidedown', 'hidecilick', 'hidepc']);" data-active="download" data-index="12" class="pc_temp_btn_download" title="下载" hidefocus="true">下载</a>
                                        <a href="javascript:;" data-active="share" data-index="12" class="pc_temp_btn_share" title="分享" hidefocus="true">分享</a>
                                        <span class="pc_temp_time">
                                                                                                                3:18
                                        </span>
                                    </span>
                                </li>
                                                            <li class=" " title="蒋雪儿 - 一生等你" data-index="13">
                                    <span class="pc_temp_btn_check pc_temp_btn_checked" data-index="13"></span>
                                    <span class="pc_temp_coverlayer"></span>
                                    <span class="pc_temp_num">
                                                                                                                14
                                                                        </span>
                                                                    <span class="pc_temp_tips_l">
                                        <i class="pc_temp_icon_new" title="新入榜"></i>
                                    </span>
                                                                    <a href="http://www.kugou.com/song/rdbvkf5.html" data-active="playDwn" data-index="13" class="pc_temp_songname" title="蒋雪儿 - 一生等你" hidefocus="true">蒋雪儿 - 一生等你</a>
                                    <span class="pc_temp_tips_r">
                                                                            <a href="javascript:;" data-active="play" data-index="13" class="pc_temp_btn_listen" title="播放" hidefocus="true">播放</a>
                                        <a href="javascript:;" onclick="_hmt.push(['_trackEvent', 'hidedown', 'hidecilick', 'hidepc']);" data-active="download" data-index="13" class="pc_temp_btn_download" title="下载" hidefocus="true">下载</a>
                                        <a href="javascript:;" data-active="share" data-index="13" class="pc_temp_btn_share" title="分享" hidefocus="true">分享</a>
                                        <span class="pc_temp_time">
                                                                                                                3:49
                                        </span>
                                    </span>
                                </li>
                                                    
                                                        </ul>
                        </div>
    '''
    
    result = re.search('<li.*?title=(.*?)\sdata', html, re.S)
    print(result.group(1))
    
    

    结果如下:

    "冷漠、李磊 - 我们想要的"
    

    说明:

    • search() 方法只返回匹配到的第一个值,想获取所有的信息,就要用到下面的方法。

    findall()

    该方法在匹配的时候会查找所有的符合规则的内容并返回,如果没有查到就返回None。
    仍然用上面的例子:

    import re
    
    
    html = '''
    <div class="pc_temp_songlist  pc_rank_songlist_short">
                            <ul>
                                                            <li class="lengmo" title="冷漠、李磊 - 我们想要的" data-index="12">
                                    <span class="pc_temp_btn_check pc_temp_btn_checked" data-index="12"></span>
                                    <span class="pc_temp_coverlayer"></span>
                                    <span class="pc_temp_num">
                                                                                                                13
                                                                        </span>
                                                                    <span class="pc_temp_tips_l">
                                        <i class="pc_temp_icon_new" title="新入榜"></i>
                                    </span>
                                                                    <a href="http://www.kugou.com/song/pyaswf9.html" data-active="playDwn" data-index="12" class="pc_temp_songname" title="冷漠、李磊 - 我们想要的" hidefocus="true">冷漠、李磊 - 我们想要的</a>
                                    <span class="pc_temp_tips_r">
                                                                            <a href="javascript:;" data-active="play" data-index="12" class="pc_temp_btn_listen" title="播放" hidefocus="true">播放</a>
                                        <a href="javascript:;" onclick="_hmt.push(['_trackEvent', 'hidedown', 'hidecilick', 'hidepc']);" data-active="download" data-index="12" class="pc_temp_btn_download" title="下载" hidefocus="true">下载</a>
                                        <a href="javascript:;" data-active="share" data-index="12" class="pc_temp_btn_share" title="分享" hidefocus="true">分享</a>
                                        <span class="pc_temp_time">
                                                                                                                3:18
                                        </span>
                                    </span>
                                </li>
                                                            <li class="jiangxueer" title="蒋雪儿 - 一生等你" data-index="13">
                                    <span class="pc_temp_btn_check pc_temp_btn_checked" data-index="13"></span>
                                    <span class="pc_temp_coverlayer"></span>
                                    <span class="pc_temp_num">
                                                                                                                14
                                                                        </span>
                                                                    <span class="pc_temp_tips_l">
                                        <i class="pc_temp_icon_new" title="新入榜"></i>
                                    </span>
                                                                    <a href="http://www.kugou.com/song/rdbvkf5.html" data-active="playDwn" data-index="13" class="pc_temp_songname" title="蒋雪儿 - 一生等你" hidefocus="true">蒋雪儿 - 一生等你</a>
                                    <span class="pc_temp_tips_r">
                                                                            <a href="javascript:;" data-active="play" data-index="13" class="pc_temp_btn_listen" title="播放" hidefocus="true">播放</a>
                                        <a href="javascript:;" onclick="_hmt.push(['_trackEvent', 'hidedown', 'hidecilick', 'hidepc']);" data-active="download" data-index="13" class="pc_temp_btn_download" title="下载" hidefocus="true">下载</a>
                                        <a href="javascript:;" data-active="share" data-index="13" class="pc_temp_btn_share" title="分享" hidefocus="true">分享</a>
                                        <span class="pc_temp_time">
                                                                                                                3:49
                                        </span>
                                    </span>
                                </li>
                                                    
                                                        </ul>
                        </div>
    '''
    result = re.findall('<li.*?title=(.*?)\sdata', html, re.S)
    print(result)
    

    结果如下:

    ['"冷漠、李磊 - 我们想要的"', '"蒋雪儿 - 一生等你"']
    

    说明:返回的结果是一个列表。

    sub()

    有时候我们用正则表达式提取信息的时候,会遇到原始文本太长,无用信息太多的情况。就这用到了sub() 方法:通过替换的方式将文本进行精简,比如:去掉某一个标签。
    借用上述的例子:

    result = re.sub('<span.*?>|</span>|<i.*?>|</i>|<a.*?>|</a>', " ", html)
    print(result)
    

    结果如下:

    <div class="pc_temp_songlist  pc_rank_songlist_short">
                            <ul>
                                                            <li class="lengmo" title="冷漠、李磊 - 我们想要的" data-index="12">
                                       
                                                                                                                13
                         冷漠、李磊 - 我们想要的 
                                     
                                                                             播放 
                                         下载 
                                         分享 
                                         
                                                                                                                3:18
                                     
                                </li>
                                                            <li class="jiangxueer" title="蒋雪儿 - 一生等你" data-index="13">
                                                                                                        14
                                                                     蒋雪儿 - 一生等你 
                                     
                                                                             播放 
                                         下载 
                                         分享 
                                         
                                                                                                                3:49
                                         
                                     
                                </li>
                                                    
                                                        </ul>
                        </div>
    
    

    说明:

    • 该方法的参数:第一个是正则法则、第二个是要插入的字符、第三个是原始字符串
    • 清理数据经常用到

    compile()

    前面介绍的几种方法,在匹配字符串之前都要先编写匹配规则,如果要处理好多个类似的文本,是不是要写好多个一样的匹配规则呢?
    这里介绍一下 compile() 方法,将正则字符串编译成正则表达式对象,一遍在后面的匹配中复用。实例代码如下:

    import re
    
    content1 = '2016-12-17 12:00'
    content2 = '2017-12-05 12:00'
    content3 = '2018-12-25 12:00'
    
    # 将时间去掉
    pattern = re.compile('\d{2}:\d{2}')
    
    result1 = re.sub(pattern, " ", content1)
    print(result1)
    result2 = re.sub(pattern, " ", content2)
    print(result2)
    result3 = re.sub(pattern, " ", content3)
    print(result3)
    

    结果如下:

    2016-12-17  
    2017-12-05  
    2018-12-25  
    

    到此为止,正则表达式的基本用法就介绍完了,后面会通过具体的实例来讲解正则方法,先附上一个demo

    相关文章

      网友评论

          本文标题:Python / re 正则表达式

          本文链接:https://www.haomeiwen.com/subject/fgdcqqtx.html