正则表达式(re模块)

正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串,在文本处理方面功能非常强大,也经常用作爬虫,来爬取特定内容,Python本身不支持正则,但是通过导入re模块,Python也能用正则表达式,正则表达式默认以单行开始匹配的

在线测试:

.

匹配任意字符,换行符‘\n’除外

\

转义字符

[…]

字符集类,对应位置可以是集中任意字符,[abcde]==[a-e],[^abcd]表示不是集中的任意一个,特殊符号前要加\

\d

数字[0-9]

\D

非数字

\s

空白字符[空格、\t、\r、\n、\f、\v]

\S

非空白字符

\w

单词字符[A-Za-z0-9]

\W

非单词字符

 

*

匹配字符0次或无数次

+

1次或无数次

0次或1次

{m}

m次

{m,n}

m到n次

*? {m,n}?

使匹配变成非贪婪模式

 

^

匹配开头,在多行模式中匹配每一行开头

$

匹配结尾

\A

仅匹配字符串开头

\Z

仅字符串结尾

\b

匹配\w和\W之间,a\b!bcàa!bc

\B

[^\b] , a\B\bcàabc

|

匹配左右任意一个,先左后右,左成功则跳过右,

若没有被包括在()内,范围是整个表达式,

(…)

被括起来的内容作为分组

 

1.    re.split()分隔符

import re

ss='adb4kss4siko n4bkd4g e5kop'

bb=re.split('4|5',ss)

print(bb)

 #返回 ['adb', 'ks s', 'siko n', 'bkd', 'g e', 'kop']

2.    re.match方法

尝试从字符串的起始位置开始匹配,若起始位置匹配不成功的话,返回none

^匹配开头,$匹配结尾

1>  

import re

content='hello 4654332 gre 4532 bkios igb fs423ge aaa'

result=re.match('^hello.*aaa$',content)  #  .*范匹配,^匹配开头,$匹配结尾print(result.group())#返回结果hello 4654332 gre 4532 bkios igb fs423ge aaa

***********************************************

result=re.match('^hello\s(\d+)\s.*aaa$',content)

print(result.group(1))#返回4654332,无1返回全部,1表示第一个()匹配的内容print(result.span(1)) #返回 (6, 13) ,无1返回(0,44)

2> 贪婪匹配

使用‘.*’ 尽可能匹配多的字符

import re

content='hello 465789 gre 4532 bkios igb fsge aaa'

result=re.match('^hello.*(\d+).*aaa$',content) 

priont(result.group(1)) #返回2,‘.*’多匹配,(\d)只剩最后的2

3>  非贪婪模式

import re

content='hello 465789 gre 4532 bkios igb fsge aaa'

result=re.match('^h.*?(\d+).*aa$',content)  #465789, ‘.*’尽可能少的匹配

result=re.match('^h.*?(\w+).*aa$',content)  #ello,除下h头,匹配直到不符条件

3.    ’.*‘默认匹配不到换行符 ,re.S用来匹配\n等

import re

content='''hello525435

world_isnkgeghgfn $5bg'''              

result=re.match('^he.*?\$5bg$',content,re.S)  #$需用\转义

print(result.group())  #正常返回并带有换行,去除re.S则失败

************************************************

\s匹配空格,\s*匹配空格与换行

strip消除字符串两边空格

4.    re.search方法

扫描整个字符串并返回第一个成功的匹配

import re

content ='Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'

result =re.search('Hello.*?(\d+).*?Demo',content)

print(result.group())

 #返回Hello 1234567 World_This is a Regex Demo

5.    re.sub方法

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

import re

content ='abcdcdef'

result =re.sub('ef','cd',content)

print(result)   #返回abcdcdcd

result =re.subn('ef','cd',content)

print(result)   #返回('abcdcdcd', 1),替换次数

6.    re.compile方法

把字符串编译成正则表达式对象,将一个正则表达式串编译成正则对象,以便于复用该匹配模式

import re

content='''hello1234556 word jgmnlg

is a freestyle'''

pattern=re.compile('hello.*tyle',re.S) 

result=re.match(pattern,content)

print(result.group())

7.    re.findall方法

搜索字符串,以列表形式返回全部符合条件的匹配到的字符串

8.    应用实例

import re

html = '''<div id='songs-list'>

       <h2>经典老歌</h2>

       <p>

           经典老歌列表

       </p>

       <ul id='list'>

       <li data-view='2'>一路上有你</li> 

       <li data-view='7'>   

           <a href='/2.mp3' singer='任贤齐'>沧海一声笑</a>

       </li>

       <li data-view='4'>

           <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='邓丽君'><iclass='fa fa-user'></i>但愿人长久</a>

       </li>

       </ul>

</div>'''

result=re.search("<li.*?active.*?f=\'(.*?)\'\ssinger='(.*?)'>(.*?).*?</li>",html,re.S)

print(result.group(1))

print(result.group(2))

print(result.group(3)) #返回结果:/3.mp3  和  齐秦 (.*?).*?,group(3)被覆盖

#-->result=re.search('<li.*?f=\'(.*?)\'.*?r=\'(.*?)\'>(.*?)</a>',html,re.S)

#返回 /2.mp3  任贤齐  沧海一声笑

#-->去掉re.S,返回/4.mp3  beyond  光辉岁月(re.search匹配成功)

*re.findall

results = re.findall("<li.*?href='(.*?)'.*?singer='(.*?)'>(.*?)</a>",html,re.S)

for result in results:      #列表中嵌套元组

print(result)#返回元组

                             

results =re.findall("<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>",html,re.S)

for result in results:

print(result)

 

9.    原生字符串

import re

#“\b”在ASCII 字符中代表退格键,\b”在正则表达式中代表“匹配一个单词边界”

print(re.findall("\bblow","jason blowcat"))

#这里\b代表退格键,所以没有匹配到,返回空列表

print(re.findall("\\bblow","jason blowcat"))

 #用\转义后这里就匹配到了,返回 ['blow']

print(re.findall(r"\bblow","jasonblow cat"))

#用原生字符串后就不需要转义了 ['blow']

在正则表达式里使用“\d”,没用原始字符串,也没出现什么问题。那是因为ASCII 里没有对应的特殊字符,所以正则表达式编译器能够知道你指的是一个十进制数字。但是我们写代码本着严谨简单的原理,最好是都写成原生字符串的格式。