正则表达式

1.正则表达式

正则表达式用来匹配一段字符串,如果字符串符合正则表达式的规则要求,就会被提取出来。

开源中国提供的正则表达式测试工具:https://tool.oschina.net/regex/#

 

2.match()

Python的re库提供了整个正则表达式的实现,一个常用的匹配方法是match()。

match()方法会尝试从字符串的起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配,就返回 None。

代码:

import re

content = 'Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}', content)
#\d后可以跟{4}代表匹配前面的规则4次
#第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串

print(result)
print(result.group())
print(result.span())

运行结果:输出

41
<re.Match object; span=(0, 25), match='Hello 123 4567 World_This'>
Hello 123 4567 World_This
(0, 25)

 

匹配目标

可以使用括号()将想提取的子字符串括起来,()实际上标记了一个子表达式的开始和结束位置,

被标记的每个子表达式会依次对应每一个分组,调用group()方法传入分组引索即可获取提取的结果

代码:

import re

content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^Hello\s(\d+)\sWorld',content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())

运行结果:输出

<re.Match object; span=(0, 19), match='Hello 1234567 World'>
Hello 1234567 World
1234567
(0, 19)

假如正则表达式后面还有其他(),可以依次用group(2)、group(3)来取。

 

通用匹配

. 点可以匹配任意字符, * 星代表匹配前面的字符无限次。

使用这些改写上面的正则表达式。

代码:

import re

content='Hello 123 4567 World_This is a Regex Demo'
result=re.match('^Hello.*Demo$',content)
print(result)
print(result.group())
print(result.span())

运行结果:输出

<re.Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
Hello 123 4567 World_This is a Regex Demo
(0, 41)

中间部分全部被忽略了。

 

贪婪与非贪婪

贪婪匹配下.*会匹配尽可能多的的字符。

非贪婪匹配下.*?会匹配尽可能少的字符。

如果非贪婪匹配在字符串结尾,可能会匹配不到任何内容。

所以在匹配时,在字符串中间尽可能使用非贪婪匹配。

 

修饰符

正则表达式可以包含一些可选标志修饰符来控制匹配模式。

如果在字符串中加入换行符。

代码:

import re

content='''Hello 123 4567 World_This
is a Regex Demo
'''
result=re.match('^He.*?(\d+).*?Demo$',content)
print(result.group(1))

运行结果会报错。

加一个修饰符re.S就可以修复这个错误。

result=re.match('^He.*?(\d+).*?Demo$',content,re.S)

re.S的作用是使 . 可以匹配换行符在内的所有字符,除此之外还有许多修饰符。

 

转义匹配

如果目标字符串包含 . , 可以在前面加反斜线转义即可。

代码:

import re

content='www.baidu.com'
result=re.match('www\.baidu\.com',content)
print(result)

运行结果:输出

<re.Match object; span=(0, 13), match='www.baidu.com'>

成功匹配所有字符串。

 

3.search()

match()是从开头匹配的,一旦开头不匹配,那么整个匹配就失败了,所以它更适合用来测试某个字符串是否符合某个正则表达式的规则。

search()方法在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果,如果搜索完了还没有找到,就返回None。

代码:

#coding:gbk
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)
if result:
    print(result.group(1),result.group(2))

运行结果:输出

齐秦  往事随风

 

4.findall()

findall()方法搜索整个字符串,获取匹配正则表达式的所有内容。

代码:

#coding:gbk
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)
print(type(results))
for result in results:
    print(result)
    print(result[0],result[1],result[2])

运行结果:输出

[('/2.mp3', '任贤齐', ' 沧海一声笑 '), ('/3.mp3', '齐秦', ' 往事随风 '), ('/4.mp3', 'beyond', ' 光辉岁月 '), ('/5.mp3', '陈慧琳', ' 记事本 '), ('/6.mp3', '邓丽君', ' 但愿人长久 ')]
<class 'list'>
('/2.mp3', '任贤齐', ' 沧海一声笑 ')
/2.mp3 任贤齐  沧海一声笑
('/3.mp3', '齐秦', ' 往事随风 ')
/3.mp3 齐秦  往事随风
('/4.mp3', 'beyond', ' 光辉岁月 ')
/4.mp3 beyond  光辉岁月
('/5.mp3', '陈慧琳', ' 记事本 ')
/5.mp3 陈慧琳  记事本
('/6.mp3', '邓丽君', ' 但愿人长久 ')
/6.mp3 邓丽君  但愿人长久

返回的列表中的每个元素都是元组类型。

 

5.sub()

sub()方法可以利用正则表达式来修改文本。

代码:

import re

content='4j559fbjfd9fsjb934jv'
content=re.sub('\d+','',content)
print(content)

运行结果:输出

jfbjfdfsjbjv

可以将其中的数字去除掉。

或者将文本中的a节点全部去掉。

代码:

#coding:gbk
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>'''
html=re.sub('<a.*?>|</a>','',html)
print(html)
result=re.findall('<li.*?>(.*?)</li>',html,re.S)
for result in results:
    print(result.strip())

运行结果:输出

<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">
 沧海一声笑
</li>
<li data-view="4" class="active">
 往事随风
</li>
<li data-view="6"> 光辉岁月 </li>
<li data-view="5"> 记事本 </li>
<li data-view="5">
 但愿人长久
</li>
</ul>
</div>
Traceback (most recent call last):
  File "retest_8.py", line 27, in <module>
    for result in results:
NameError: name 'results' is not defined
PS D:\spider> python retest_8.py
<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">
 沧海一声笑
</li>
<li data-view="4" class="active">
 往事随风
</li>
<li data-view="6"> 光辉岁月 </li>
<li data-view="5"> 记事本 </li>
<li data-view="5">
 但愿人长久
</li>
</ul>
</div>
一路上有你
沧海一声笑
往事随风
光辉岁月
记事本
但愿人长久

 

6.compile()

compile()方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用。

代码:

import re

content1='2016-12-15 12:00'
content2='2016-12-17 12:55'
content3='2016-12-22 13:21'
pattern=re.compile('\d{2}:\d{2}')
#将正则表达式编译成为一个正则表达式对象,以便复用

result1=re.sub(pattern, '', content1)
result2=re.sub(pattern, '', content2)
result3=re.sub(pattern, '', content3)
print(result1, result2, result3)

运行结果:输出

2016-12-15  2016-12-17  2016-12-22

compile()方法也可以传入修饰符,如re.S。

 

参考用书《python3网络爬虫开发实战》

posted @ 2020-12-18 15:08  Hao_ran  阅读(125)  评论(0编辑  收藏  举报