爬虫之正则表达式search()用法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/86361162

一 match()的不足

1 点睛

match()方法是从字符串的开头开始匹配的,一旦开头不匹配,那么整个匹配就失败了。

2 代码

import re
# 这里的字符串以Extra开头,但是正则表达式以Hello开头,
# 整个正则表达式是字符串的一部分,但是这样匹配是失败的。
content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
result = re.match('Hello.*?(\d+).*?Demo', content)
print(result)

3 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.py
None

4 说明

因为match()方法在使用时需要考虑到开头的内容,这在做匹配时并不方便。它更适合用来检测某个字符串是否符合某个正则表达式的规则。

二 search()方法的引入

1 点睛

方法search(),它在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果。也就是说,正则表达式可以是字符串的一部分,在匹配时,search()方法会依次扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容,如果搜索完了还没有找到,就返回None。

2 代码

import re
# 这里的字符串以Extra开头,但是正则表达式以Hello开头,
# 整个正则表达式是字符串的一部分,但是这样匹配是失败的。
content = 'Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
# result = re.match('Hello.*?(\d+).*?Demo', content)
# 将match换成search
result = re.search('Hello.*?(\d+).*?Demo', content)
print(result)

3 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.py
<_sre.SRE_Match object; span=(13, 53), match='Hello 1234567 World_This is a Regex Demo'>

4 说明

为了匹配方便,我们可以尽量使用search()方法。

三 实战

1 需要爬取的文本

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="邓丽君"><i class="fa fa-user"></i>但愿人长久</a>
        </li>
    </ul>
</div>'''

2 需求

可以观察到,ul节点里有许多li节点,其中li节点中有的包含a节点,有的不包含a节点,a节点还有一些相应的属性——超链接和歌手名。

首先,我们尝试提取class为active的li节点内部的超链接包含的歌手名和歌名,此时需要提取第三个li节点下a节点的singer属性和文本。

3 分析

此时正则表达式可以以li开头,然后寻找一个标志符active,中间的部分可以用.*?来匹配。接下来,要提取singer这个属性值,所以还需要写入singer="(.*?)",这里需要提取的部分用小括号括起来,以便用group()方法提取出来,它的两侧边界是双引号。然后还需要匹配a节点的文本,其中它的左边界是>,右边界是</a>。然后目标内容依然用(.*?)来匹配,所以最后的正则表达式就变成了:

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

然后再调用search()方法,它会搜索整个HTML文本,找到符合正则表达式的第一个内容返回。

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

4 代码

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="邓丽君"><i class="fa fa-user"></i>但愿人长久</a>
        </li>
    </ul>
</div>'''
import re
result = re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>', html, re.S)
if result:
    print(result.group(1), result.group(2))

5 运行结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.py
齐秦 往事随风

6 说明

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

可以看到,这正是class为active的li节点内部的超链接包含的歌手名和歌名。

7 去掉正则表达式中的 active

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

8 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.py
任贤齐 沧海一声笑

9 说明

把active标签去掉后,从字符串开头开始搜索,此时符合条件的节点就变成了第二个li节点,后面的就不再匹配,所以运行结果就变成第二个li节点中的内容。

10 去掉re.S

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

11 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.py
beyond 光辉岁月

12 说明

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

由于绝大部分的HTML文本都包含了换行符,所以尽量都需要加上re.S修饰符,以免出现匹配不到的问题。

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/86361162