Python / re 正则表达式

2018-11-22  本文已影响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))

结果如下:

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

说明:

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

上一篇下一篇

猜你喜欢

热点阅读