常用匹配规则
match()
从字符串的起始位置开始匹配,返回SRE_MATCH对象
importre
#文本内容
content='WOW! Stunning sunrise seen this morning from Belle Plaine, Minnesota'
#文本长度
print(len(content))
#匹配特征
pattern='^\w!\sStunning sunrise\s\w'
result=re.match(pattern,content)
print(result)
#匹配内容
print(result.group())
#匹配范围
print(result.span())
#输出结果
68
WOW!Stunningsunriseseen
(,26)
"^"为匹配字符串的开头(对于match方法来说,可以不加,因为是必须从开始位置匹配)
"\w"表示匹配字母、数字、下划线共3位。
"\s"表示匹配空格。
设定的pattern中,仅匹配sunrise后+空格(\s)+4个字母(\w)。
group()方法,返回了匹配的结果。
span()方法返回了匹配的范围。
提取匹配字段
如上文中,想提取sunrise和seen,可以通过将想提取的子字符串用"()"括起来
pattern='^\w!\sStunning (sunrise)\s(\w)\s\w\s\w'
然后通过group()方法调用分组索引
>>>print(result.group(1))
sunrise
>>>print(result.group(2))
seen
Tips小技巧:为了简化print某些对索引的输出,我们可以使用匿名表达式
f=lambda x:print(result.group(x))
f(1)会是什么结果呢?
通用匹配
在pattern中,我们对于"\s"空格和"\w"的多次切换使用,大多时候其实是冗余操作,因此,需要用到".*"进行任意字符匹配,这里从头开始匹配结尾到Minnesota。
pattern='^\w!\sStunning (sunrise).*Plaine$'
#输出结果
f=lambdax:print(result.group(x))
f(1)
sunrise
f(2)
morning
"."可以匹配任意字符(除换行符),指定re.DOTALL标记可以匹配包括换行符在内任意字符
"*"可以匹配前面的字符无限次数,与"."组合即无限匹配
贪婪与非贪婪
什么是贪婪,这里另外举例子,如果我们想匹配数字,可能,开始想这样设计匹配特征
content='Hello 1234567 World'
pattern='^He.*(\d+).*ld'
print(result.group(0))
Hello 1234567 World
print(result.group(1))
7
发现结果只有匹配到7,这是因为".*"优先匹配了最多的字符,然后才轮到(\d+)
所以此时可以转换为非贪婪匹配,在".*"后多增加个"?"
pattern='^He.*?(\d+).*ld'
使用非贪婪匹配的时候,必须注意,在结尾使用".*?",意味着,尽可能少会少到不匹配。
修饰符
在正则表达式使用时,常常会遇到一些问题。比如,字符串换行时,发现无法匹配了
content='''Hello 123456
World'''
pattern='^He.*?(\d+).*ld'
Traceback (most recent call last):File "", line 1, inFile "", line 1, inAttributeError: 'NoneType' object has no attribute 'group'
原因是"."不能匹配换行符,所以我们这里需要使用re.S修饰,来使"."可以对换行符进行匹配
result=re.match(pattern,content,re.S)
print(result.group(1))
123456
转义匹配
对于内容中,如果本身就含有"."之类特殊字符,对这些字符进行匹配则需要用到"\"
search()
相对match()仅能从头开始匹配,search()方法允许返回整个字符串第一个匹配的特征。
findall()
需要通过一个特征匹配多组数据,findall()方法可以返回整个字符串所匹配的所有数据到列表中。
importrequests,re
headers= {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
website='https://www.bilibili.com/read/home'
rget=requests.get(website,headers=headers,timeout=3)
pattern='(.*?)
(.*?)
'
results=re.findall(pattern,rget.text,re.S)
print(results)
B站,你懂的,总有几个感觉不易于消化的内容,不放上来了,返回的是列表形式。
sub()
将匹配的字符串直接进行替换,既可以用字符串提供的replace()方法,也可以使用re模块的sub()方法
使用方法:sub(repl, string[, count])
content='u 24a0r1e 9a4 ge3n3i123u55s'
content=re.sub('\d+','',content)
自己动手
提一点,在html,xml等等作为content层面上的应用,可以通过方法将上级节点去掉,即替换为空
,'|'表示或。
count表示最多替换次数
compile()
将一段正则表达式编译为pattern对象,并且可以传入修饰符,如re.S,从而不需要在使用search()、findall()等方法时再传入re.S了
importre
content1='2018-09-16 12:00:00'
content2='''2018-09-17 12:00:00
2018-09-18 12:00:00'''
pattern=re.compile('\d:\d:\d',re.S)
pattern='\d:\d:\d'
result1=re.sub(pattern,'',content1)
result2=re.sub(pattern,'',content2)
print('r1:\nr2:'.format(result1,result2))
r1:2018-09-16r2:2018-09-172018-09-18
split()
由于某些情况需要按照某些特征作为分隔符,提取为列表数据,使用split()
importre
content='''2018-09-17 12:13:14
2018-09-18 12:18:07'''
pattern=re.compile('-|\s|:',re.S)
result=re.split(pattern,content)
print(result)
['2018', '09', '17', '12', '13', '14', '2018', '09', '18', '12', '18', '07']
针对时间的"-","空格",":"作为分隔符提取
实际上\s并不需要,re.S也不需要,仅做列出方案
领取专属 10元无门槛券
私享最新 技术干货