爬虫之正则表达式findall()-sub()-compile()

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

一 findall()

1 点睛

search()方法,它可以返回匹配正则表达式的第一个内容,但是如果想要获取匹配正则表达式的所有内容,那该怎么办呢?这时就要借助findall()方法了。该方法会搜索整个字符串,然后返回匹配正则表达式的所有内容。

2 代码

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
# 想获取所有a节点的超链接、歌手和歌名,就可以将search()方法换成findall()方法。
# 如果有返回结果的话,就是列表类型,所以需要遍历一下来依次获取每组内容。
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])

3 运行结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.py
[('/2.mp3', '任贤齐', '沧海一声笑'), ('/3.mp3', '齐秦', '往事随风'), ('/4.mp3', 'beyond', '光辉岁月'), ('/5.mp3', '陈慧琳', '记事本'), ('/6.mp3', '邓丽君', '<i class="fa fa-user"></i>但愿人长久')]
<class 'list'>
('/2.mp3', '任贤齐', '沧海一声笑')
/2.mp3 任贤齐 沧海一声笑
('/3.mp3', '齐秦', '往事随风')
/3.mp3 齐秦 往事随风
('/4.mp3', 'beyond', '光辉岁月')
/4.mp3 beyond 光辉岁月
('/5.mp3', '陈慧琳', '记事本')
/5.mp3 陈慧琳 记事本
('/6.mp3', '邓丽君', '<i class="fa fa-user"></i>但愿人长久')
/6.mp3 邓丽君 <i class="fa fa-user"></i>但愿人长久

4 说明

可以看到,返回的列表中的每个元素都是元组类型,我们用对应的索引依次取出即可。

如果只是获取第一个内容,可以用search()方法。当需要提取多个内容时,可以用findall()方法。

二 sub()

1 点睛

除了使用正则表达式提取信息外,有时候还需要借助它来修改文本。比如,想要把一串文本中的所有数字都去掉,如果只用字符串的replace()方法,那就太烦琐了,这时可以借助sub()方法。

2 代码

import re
# 需求:去掉一串文本中的所有数字
content = '54aK54yr5oiR54ix5L2g'
# 这里只需要给第一个参数传入\d+来匹配所有的数字,
# 第二个参数为替换成的字符串(如果去掉该参数的话,可以赋值为空),第三个参数是原字符串。
content = re.sub('\d+', '', content)
print(content)

3 结果

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

4 提取歌名方法1

4.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>'''
import re
results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>', html, re.S)
for result in results:
    print(result[1])

4.2 运行结果

一路上有你
沧海一声笑
往事随风
光辉岁月
记事本
但愿人长久

4.3 说明

直接用正则表达式来提取可能比较烦琐。

5 提取歌名方法2

5.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="邓丽君">但愿人长久</a>
        </li>
    </ul>
</div>'''
import re
# 方法1:直接提取
# results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>', html, re.S)
# for result in results:
#     print(result[1])
# 方法2:先sub,然后findall提取
html = re.sub('<a.*?>|</a>', '', html)
print(html)
results = re.findall('<li.*?>(.*?)</li>', html, re.S)
for result in results:
    print(result.strip())

5.2 结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.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>
一路上有你
沧海一声笑
往事随风
光辉岁月
记事本
但愿人长久

5.3 说明

可以看到,a节点经过sub()方法处理后就没有了,然后再通过findall()方法直接提取即可。可以看到,在适当的时候,借助sub()方法可以起到事半功倍的效果。

三 compile()

1 点睛

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

2 代码

import re
# 这里有3个日期,我们想分别将3个日期中的时间去掉,这时可以借助sub()方法。
# 该方法的第一个参数是正则表达式,但是这里没有必要重复写3个同样的正则表达式,
# 此时可以借助compile()方法将正则表达式编译成一个正则表达式对象,以便复用。
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)

3 运行结果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_3.py
2016-12-15  2016-12-17  2016-12-22

4 说明

另外,compile()还可以传入修饰符,例如re.S等修饰符,这样在search()、findall()等方法中就不需要额外传了。所以,compile()方法可以说是给正则表达式做了一层封装,以便我们更好地复用。

猜你喜欢

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