10.正则表达式基础

上一篇:9.Requests库基本使用
下一篇:11.BeautifulSoup详解

http://www.runoob.com/python3/python3-reg-expressions.html

什么是正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是 事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符”,这个“规则字符” 来表达对字符的一种过滤逻辑。

正则并不是python独有的,其他语言也都有正则
python中的正则,封装了re模块

python正则的详细讲解

常用的匹配模式

\w      匹配字母数字及下划线
\W      匹配非字母数字下划线
\s      匹配任意空白字符,等价于[\t\n\r\f]
\S      匹配任意非空字符
\d      匹配任意数字
\D      匹配任意非数字
\A      匹配字符串开始
\Z      匹配字符串结束,如果存在换行,只匹配换行前的结束字符串
\z      匹配字符串结束
\G      匹配最后匹配完成的位置
\n      匹配一个换行符
\t      匹配一个制表符 ^ 匹配字符串的开头
$       匹配字符串的末尾
.       匹配任意字符,除了换行符,re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符
[....]  用来表示一组字符,单独列出:[amk]匹配a,m或k
[^...]  不在[]中的字符:[^abc]匹配除了a,b,c之外的字符 
*       匹配0个或多个的表达式 + 匹配1个或者多个的表达式
?       匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
{n}     精确匹配n前面的表示
{m,m}   匹配n到m次由前面的正则表达式定义片段,贪婪模式
a|b     匹配a或者b
()      匹配括号内的表达式,也表示一个组

re.match()

语法格式:

re.match(pattern,string,flags=0)
#三个参数:
#1. pattern;正则表达式
#2. string: 被筛选的字符串
#3. flags:匹配模式

尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配的话,match()就会返回None

# 起始位置匹配,否则报错
print(re.match("^1\d{7}9$","123456789").group())    # 123456789
print(re.match("^2\d{7}9$","123456789").group())    # 报错
print(re.match("^2\d{6}9$","23456789").group())     # 23456789

最常规的匹配

import re

content= "hello"
result = re.match('^h\w\w\wo$',content)
print(len(content))         # 获取字符串的长度 5
print(result)               # <_sre.SRE_Match object; span=(0, 5), match='hello'>
print(result.group())       # 输出匹配结果     hello
print(result.span())        # 匹配结果范围    (0, 5)
#字符多的话
content = "helloworld 123 aaa _world"
result  = re.match( "^hello\w\w\w\w\w\s\d\d\d\s\w\w\w\s_world$",content) 
print(content.__len__())    # 字符串长度 25
print(result.group())       # helloworld 123 aaa _world

有多少个字符就要写多少个,多的可以简略写

# \w\w\w\w\w==\w{5}
re_math2 = "^hello\w{5}\s\d\d\d\s\w\w\w\s_world$"
result2  = re.match(re_math,content) 
print(result2.group())
# helloworld 123 aaa _world 

结果同样

泛匹配

#其实相对来说上面的方式并不是非常方便,其实可以将上述的正则规则进行更改
content = "helloworld 123 aaa _world"
re_math = "^he.*_world$"
result  = re.match(re_math,content) 
print(content.__len__())    # 字符串长度 25
print(result.group())       # helloworld 123 aaa _world

匹配目标

#如果为了匹配字符串中具体的目标,则需要通过()括起来,例子如下:
content = "helloworld 123 aaa _world"
re_math = "^hello(\w{5})\s(\d\d\d)\s\w\w\w\s_world$"
result  = re.match(re_math,content) 
print(result.group(1))      # world
print(result.group(2))      # world
# 注意,group(n) n是几,就是对应第几个括号

贪婪匹配

content = "HelloWorld 12345678945646465 a demo"
re_math = "^HelloWorld\s.*?(\d+).*o$"
result = re.match(re_math,content)
print(result.group(1))      # 1
# .* 会尽可能的多匹配,所以只能匹配到最后一个
# 如果加上 ?(\d+) ?就可以全匹配d

匹配模式

很多时候匹配的内容是存在换行的问题的,这个时候的就需要用到匹配模式re.S来匹配换行的内容

content = """HelloWorld 123456 a re_math
my name is lsy
"""

result =re.match('^He.*(\d+).*?lsy$',content,re.S)
print(result)
print(result.group())   #只有第一行
print(result.group(1))  #正常

转义:

当我们要匹配的内容中存在特殊字符的时候,就需要用到转移符号,例子如下:

'''
import re

content= "price is $5.00"

result = re.match('price is $5.00',content)
print(result)
print(result.group())
'''
对上面的一个小结:尽量使用泛匹配,使用括号得到匹配目标,尽量使用非贪婪模式,有换行符就用re.S强调re.match是从字符串的起始位置匹配一个模式

re.search

re.search扫描整个字符串返回第一个成功匹配的结果

content = "hello haha hello start is_Me lalal 12121 a Re end things"

result = re.search("start.*?(\d+).*?end",content)
print(result)
print(result.group())
print(result.group(1))
# 不需要在写^以及$,因为search是扫描整个字符串

示例:

import re

html = '''<div id="songs-list">
    <h2 class="title">经典老歌</h2>
    <p class="introduction">
        经典老歌列表
    </p>
    <ul id="list" class="list-group">
        <li data-view="2">一路上有你</li>
        <li data-view="7">
            <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
        </li>
        <li data-view="4" class="active">
            <a href="/3.mp3" singer="齐秦">往事随风</a>
        </li>
        <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
        <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
        <li data-view="5">
            <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
        </li>
    </ul>
</div>'''

result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>',html,re.S)
# 注意看有没有re.S换行,
print(result)
print(result.groups())
print(result.group(1))
print(result.group(2))

re.findall

搜索字符串,以列表的形式返回全部能匹配的子串

代码例子如下:

import re

html = '''<div id="songs-list">
    <h2 class="title">经典老歌</h2>
    <p class="introduction">
        经典老歌列表
    </p>
    <ul id="list" class="list-group">
        <li data-view="2">一路上有你</li>
        <li data-view="7">
            <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
        </li>
        <li data-view="4" class="active">
            <a href="/3.mp3" singer="齐秦">往事随风</a>
        </li>
        <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
        <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
        <li data-view="5">
            <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
        </li>
    </ul>
</div>'''

results = re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>', html, re.S)
print(results)
#[('/2.mp3', '任贤齐', '沧海一声笑'), ('/3.mp3', '齐秦', '往事随风'), ('/4.mp3', 'beyond', '光辉岁月'), ('/5.mp3', '陈慧琳', '记事本'), ('/6.mp3', '邓丽君', '但愿人长久')]

print(type(results))            
# <class 'list'>

for result in results:
    print(result)
    print(result[0], result[1], result[2])
'''('/2.mp3', '任贤齐', '沧海一声笑')
/2.mp3 任贤齐 沧海一声笑
('/3.mp3', '齐秦', '往事随风')
/3.mp3 齐秦 往事随风
('/4.mp3', 'beyond', '光辉岁月')
/4.mp3 beyond 光辉岁月
('/5.mp3', '陈慧琳', '记事本')
/5.mp3 陈慧琳 记事本
('/6.mp3', '邓丽君', '但愿人长久')
/6.mp3 邓丽君 但愿人长久
'''

结果:


image.png

例子2

import re

html = '''<div id="songs-list">
    <h2 class="title">经典老歌</h2>
    <p class="introduction">
        经典老歌列表
    </p>
    <ul id="list" class="list-group">
        <li data-view="2">一路上有你</li>
        <li data-view="7">
            <a href="/2.mp3" singer="任贤齐">沧海一声笑</a>
        </li>
        <li data-view="4" class="active">
            <a href="/3.mp3" singer="齐秦">往事随风</a>
        </li>
        <li data-view="6"><a href="/4.mp3" singer="beyond">光辉岁月</a></li>
        <li data-view="5"><a href="/5.mp3" singer="陈慧琳">记事本</a></li>
        <li data-view="5">
            <a href="/6.mp3" singer="邓丽君">但愿人长久</a>
        </li>
    </ul>
</div>'''

results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S)
print(results)
for result in results:
    print(result[1])

结果如下:


image.png
  • 总结:
  1. \s*? 这种用法其实就是为了解决有的有换行,有的没有换行的问题

  2. (<a.*?>)? 这种用法是因为html中有的有a标签,有的没有的,?表示匹配一个或0个,正好可以用于匹配

re.sub

替换字符串中每一个匹配的子串后返回替换后的字符串

re.sub(正则表达式,替换成的字符串,原字符串)
content = "ello haha hello start is_Me lalal 12121 a Re end things"

content = re.sub('\d+','    ',content)
print(content)
# 所有的数字都会被替代为一个空格,‘’内有几个空格是有效的
在有些情况下我们替换字符的时候,还想获取我们匹配的字符串,然后在后面添加一些内容,可以通过下面方式实现:
content = "Extra things hello 123455 World_this is a regex Demo extra things"
# \1是获取第一个匹配的结果,为了防止转义字符的问题,我们需要在前面加上r
content = re.sub('(\d+)',r'\1 7890',content)
print(content)

结果,在123455后面加上“ 空格7890”

re.compile

content= """hello 12345 world_this
123 fan
"""

pattern =re.compile("hello.*fan",re.S)

result = re.match(pattern,content)
print(result)
print(result.group())

正则的综合练习

将正则表达式编译成正则表达式对象,方便复用该正则表达式
上一篇:9.Requests库基本使用
下一篇:11.BeautifulSoup详解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容