【Python3 爬虫学习笔记】基本库的使用 10—— 正则表达式 3

3.search()

mathch()方法是从字符串的开头开始匹配的,一旦开头不匹配,那么整个匹配就失败了。因为match()方法在使用时需要考虑到开头的内容,这在匹配时并不方便。它更适合用来检测某个字符串是否符合某个正则表达式的规则。
search()方法在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果。也就是说,正则表达式可以是字符串的一部分,在匹配时,search()方法会依次扫描字符串,知道找到第一个符合规则的字符串,然后返回匹配内容,如果搜索完了还没有找到,就返回None。

import re

content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.search('Hello.*?(\d+).*?Demo',content)
print(result)

运行结果:

<_sre.SRE_Match object; span=(13, 53), match='Hello 1234567 World_This is a Regex Demo'>

这里有一段待匹配的HTML文本,接下来写几个正则表达式实例来实现相应信息的提取:

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>'''

可以观察到,ul节点里有很多li节点,其中li节点中有的包含a节点,有的不包含a节点,a节点还有一些相应的属性——超链接和歌手名。
首先,我们尝试提取class为active的li节点内部的超链接包含的歌手名和歌名,此时需要提取第三个li节点下a节点的singer属性和文本。
此时正则表达式可以以li开头,然后寻找一个标志符active,中间的部分可用.*?来匹配。接下来,要提取singer这个属性值,所以还需要写入singer="(.星?)",这里需要提取的部分用小括号括起来,以便用group()方法提取出来,它的两侧边界是双引号。然后还需要匹配a节点的文本,其中它的左边界是>,右边界是</ a>。然后目标内容易依然用(.星?)来匹配,所以最后的正则表达式就变成了:

<li.*?active.*?singer="(.*?)">(.*?)</a>

另外,由于代码有换行,所以这里第三个参数需要传入re.S。整个匹配代码如下:

import re

result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>', html, re.S)
if result:
    print(result.group(1), result.group(2))

由于需要获取的歌手和歌名都已经用小括号包围,所以可以用group()方法获取。
运行结果:

齐秦 往事如风

可以看到,这正是class为active的li节点内部的超链接包含的歌手名和歌名。
如果正则表达式不加active(也就是匹配不带class为active的节点内容),改动代码如下:

import re

result = re.search('<li.*?singer="(.*?)">(.*?)</a>', html, re.S)
if result:
    print(result.group(1), result.group(2))

结果变为:

任贤齐 沧海一声笑

把active标签去掉后,从字符串开头开始搜索,此时符合条件的节点就变成了第二个li节点,后面的就不再匹配,所以运行结果就变成第二个li节点中的内容。
注意,在上面的两次匹配中,search()方法的第三个参数都加了re.S,这使得.*?可以匹配换行,所以含有换行的li节点被匹配到了。如果去掉re.S,便会得到:

beyond 光辉岁月

可以看到,结果变成了第四个li节点的内容。这是因为第二个和第三个li节点都包含了换行符,去掉re.S之后,.*?已经不能匹配换行符,所以正则表达式不会匹配到第二个和第三个li节点,而第四个li节点中不包含换行符,所以成功匹配。

猜你喜欢

转载自blog.csdn.net/htsait4113/article/details/82778868