Python爬虫常用库(二)正则表达式

一、测试站点:正则表达式在线工具
二、语法
注:字符串前加r,或使用双反斜杠\实现对转义字符取消转义

模式描述
^指定匹配字符串的开头
$指定匹配字符串的末尾 例:*HelloDemo$指定模式串以"Hello"为首,"Demo"为尾
\w匹配一个字母/数字/下划线/汉字
\W匹配一个非字母/数字/下划线/汉字
\s匹配一个任意空白字符,等价于 [\t\n\r\f].
\S匹配一个任意非空字符
\d匹配一个任意数字,等价于 [0-9].
\D匹配一个任意非数字
.匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
*匹配0个或多个的表达式(有就匹配,没有拉倒) 例:.*匹配0或多个任意字符
+匹配1个或多个的表达式。注意:若存在语法指定字符,则至少匹配到一个
?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
()1、将括号内的正则表达式作为一个组 2、该组作为匹配目标
\1…\9匹配第n个分组,即括号中的匹配目标的内容。
|指定匹配字符串的开头
参数re.S使 . 匹配包括换行在内的所有字符,即可视为DOTALL
参数re.l匹配过程对大小写不敏感
[…]用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’
[^…]不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re{ n}精确匹配 n 个前面表达式。例如, o{2} 不能匹配 “Bob” 中的 “o”,但是能匹配 “food” 中的两个 o。
re{ n,}匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",
re{ n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
ab
(?imx)正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx)正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re)类似 (…), 但是不表示一个组
(?imx: re)在括号中使用i, m, 或 x 可选标志
(?-imx: re)在括号中不使用i, m, 或 x 可选标志
(?#…)注释.
(?= re)前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re)前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re)匹配的独立模式,省去回溯。
\A匹配字符串开始
\Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z匹配字符串结束
\G匹配最后匹配完成的位置。
\b匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\n, \t, 等.匹配一个换行符。匹配一个制表符。等
\10匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

三、re库
1、re.match
优先使用.*?非贪婪范匹配,使用()捕捉匹配目标
(1)re.match(pattern, content, flags = 0)从字符串首开始匹配。
(2)匹配成功时
re.match()返回匹配对象
re.match().group()为匹配结果串
re.match().group(i)返回匹配结果串中 语法里第i个()中的内容
re.match().span()为匹配结果串下标域

例1:常规匹配

import re

"""
从头开始匹配内容为"Hello 123 4567 World_This is a Regex Demo"的字符串
"""
content = "Hello 123 4567 World_This is a Regex Demo"
result = re.match("^Hello\s\d{3}\s\d{4}\s\w{10}\s\w{2}\s\w\s\w{5}\sDemo$", content)
if result != None:
    print(result)# <re.Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
    print(result.group())# Hello 123 4567 World_This is a Regex Demo
    print(result.span())# (0, 41)
else:
    print("Fail to match!")

例2:范匹配

import re

"""
从头开始匹配以"Hello"开头、"Demo"结尾的字符串
"""

content = "Hello 123 4567 World_This is a Regex Demo"
result = re.match("^Hello.*Demo$", content)
if result != None:
    print(result)# <re.Match object; span=(0, 41), match='Hello 123 4567 World_This is a Regex Demo'>
    print(result.group())# Hello 123 4567 World_This is a Regex Demo
    print(result.span())# (0, 41)
else:
    print("Fail to match!")

例3:匹配目标

import re

"""
从头开始匹配以"Hello"开头、"Demo"结尾的字符串中第一个内容为"1234567"的子串
"""

content = "Hello 123 4567 World_This is a Regex Demo"
result = re.match("^Hello\s(\d*).*Demo$", content)
if result != None:
    print(result)
    print(result.group(1))
    print(result.span())
else:
    print("Fail to match!")

例4:贪婪&非贪婪匹配:匹配尽可能多的语法指定字符

import re

content = "Hello 123 4567 World_This is a Regexo Demo"
result = re.match("^He.*?(\d+).*(\d+).*Demo$", content)
print(result.group())
print(result.group(1))# .*?非贪婪方式,补货整块数字123
print(result.group(2))# .*贪婪房是,4567中仅捕获到7

例5:模式串中含正则表达式语法中的字符,在左添加转义字符’'消歧

import re

content = "Price is $5.00"
result = re.match("Price is $5.00", content)
print(result)
result = re.match("Price is \$5\.00", content)
print(result)

2、re.search()
(1)扫描整个字符串,返回第一个成功的匹配

import re

content = "Extra strings Hello 123 4567 World_This is a Regex Demo Extra strings"
result = re.search("Hello.*?(\d+\s\d+).*Demo", content)
print(result)
print(result.group(1))# 123 4567

3、re.findall(pattern, content, flag = 0)
返回content中所有符合正则表达式的结果,为一个元组列表,元组中是正则表达式中括号内的内容

例1:提取html中所有歌手-歌名: 超链接

import re

class Song():
    def __init__(self, href, singer, name):
        if len(href) != 0:
            self.href = href
        else:
            self.href = "NULL"
        if len(singer) != 0:
            self.singer = singer
        else:
            self.singer = "NULL"
        if  len(name) != 0:
            self.name = name
        else:
            self.name = "NULL"

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

musics = []
results = re.findall('<li.*?>\s*?(<a href="(.*?)" singer="(.*?)">)?(\w*?)(</a>)?\s*?</li>', html)
for result in results:
    musics.append( Song( href = result[1], singer = result[2], name = result[3] ) )
for song in musics:
    print(song.singer + "-" + song.name + ": " + song.href)
'''
NULL-一路上有你: NULL
任贤齐-沧海一声笑: /2.mp3
齐秦-往事随风: /3.mp3
beyond-光辉岁月: /4.mp3
陈慧琳-记事本: /5.mp3
邓丽君-但愿人长久: /6.mp3
'''

4、re.sub(pattern, repl, content, count = 0, flags = 0)
repl为用于替换的字符串,也可为函数
count为最大替换次数
re.sub()返回content中符合正则表达式的部分被repl替换后的字符串。

例1:将所有数字转换为|NUM|

import re

content = "Extra strings Hello 4567 World_1This is2 a R3egex 1122 Demo Extra strings "
repl = "|NUM|"
result = re.sub("\d+", repl, content, 10)
print(result)
'''
Extra strings Hello |NUM| World_|NUM|This is|NUM| a R|NUM|egex |NUM| Demo Extra strings 
'''

例2:将所有数字替换为|original number:原数字|

import re

content = "first number:123, second number:456_789, third number:101112"
result = re.sub("(\d+)", r"|original number:\1 |", content, count = 4)
print(result)
'''
first number:|original number:123 |, second number:|original number:456 |_|original number:789 |, third number:|original number:101112 |
'''

例3:删除无关字符,匹配所有汉字

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.sub('<.*?>', '', html, count = 1000)
print(result)
songs = re.findall('\s*(\w*)\s', result, re.S)
for song in songs:
    print(song)
'''
    经典老歌
    
        经典老歌列表
    
    
        一路上有你
        
            沧海一声笑
        
        
            往事随风
        
        光辉岁月
        记事本
        
            但愿人长久
        
    

经典老歌
经典老歌列表
一路上有你
沧海一声笑
往事随风
光辉岁月
记事本
但愿人长久
'''

5、re.compile(pattern, flags = 0)
将正则表达式的样式编译为一个 正则表达式对象 (正则对象),可以使用re的匹配方法进行匹配匹配

prog = re.compile(pattern)
result = prog.match(string)
#等价于
result = re.match(pattern, string)

例1:提取所有单词,数字,汉字

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

pattern = re.compile('\W+(\w*)\W+')
words = pattern.findall(html)
for word in words:
    print(word, end = "、")
'''
div、songs、h2、title、h2、class、经典老歌列表、ul、list、list、li、view、一路上有你、li、view、a、2、singer、沧海一声笑、li、data、4、active、href、mp3、齐秦、a、li、view、a、4、singer、光辉岁月、li、data、5、href、mp3、陈慧琳、a、li、view、a、6、singer、但愿人长久、li、div、
'''
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值