網路爬蟲筆記【6】 Python 中的正則表示式模組與應用
阿新 • • 發佈:2018-12-17
python3 內建的 re 模組,包含了正則表示式的操作集。 re 模組的一般使用步驟如下:
- 編譯正則表示式,即使用 compile() 函式將正則表示式的字串形式編譯為一個 Pattern 物件。
- 對目標字串進行匹配,即通過 Pattern 物件提供的一些列方法對文字進行匹配查詢,獲得匹配結果(Match 物件)
- 提取結果資訊,即使用 Match 物件提供的屬性和方法獲得資訊,還可以根據需要進行其他操作。
compile 函式
Compile 函式用於編譯正則表示式,生成一個 Pattern 物件。一般使用形式如下:
import re pattern = re.compile(一個正則表示式)
成功編譯並構造 pattern 物件後,就可以使用 pattern 物件方法查詢、替換、統計目標字串中與正則表示式匹配的子字串了。pattern 物件可呼叫的方法有:
- match 方法:從起始位置開始查詢,一次匹配
- search
- fullmatch
- sub
- subn
- split
- purge
- template
- escape
- error
- findall
- finditer 事實上,這些函式不僅是物件可呼叫的,也是可以使用 re 模組直接呼叫的。
match 方法
match 方法用於在字串起始位置進行模式匹配,若匹配則返回 Match 物件,否則返回 None。
match(pattern, string, flags=0) # method of re module Try to apply the pattern at the start of the string, returning a match object, or None if no match was found. match(string=None, pos=0, endpos=None, pattern=None) # method of Pattern instance Matches zero or more characters at the beginning of the string.
下面舉例說明:
''' re 模組 compile 方法與 match 方法示例''' import re text1 = 'sdaksfhksjdfnkfsjldhfsk234sfd65s1df55s3sdf4156sd4et489t74t6' text2 = 'SDakufasdakru9013rgp2k;.,/,.;.t2,445,3/4l,63;lk,3;l,43' print('執行結果:\n') pattern = re.compile('sdak') # <_sre.SRE_Match object; span=(0, 4), match='sdak'> match = pattern.match(text1) print(match) print('---'*10) # None match = pattern.match(text2) print(match) print('---'*10) # <_sre.SRE_Match object; span=(7, 11), match='sdak'> match = pattern.match(text2, pos = 7) print(match) if match: # sdak print(match.group()) print('---'*10) # re.IGNORECASE 忽略大小寫 pattern = re.compile('sdak', flags = re.IGNORECASE) match = pattern.match(text2) if match: # SDak print(match.group()) print('---'*10)
執行結果:
<_sre.SRE_Match object; span=(0, 4), match='sdak'>
------------------------------
None
------------------------------
<_sre.SRE_Match object; span=(7, 11), match='sdak'>
sdak
------------------------------
SDak
------------------------------
Match 物件
match 物件是正則表示式匹配目標字串後返回的結果物件。它可呼叫以下方法:
- group([group1, …])方法,用於獲得一個或多個分組匹配的字串,當要獲得整個匹配的子串時,可直接使用 group() 或 group(0);
- start([group]) 方法用於獲取分組匹配的子串在整個字串中的起始位置(子串第一個字元的索引),引數預設值為 0;
- end([group]) 方法用於獲取分組匹配的子串在整個字串中的結束位置(子串最後一個字元的索引+1),引數預設值為 0;
- span([group]) 方法返回 (start(group), end(group))。
import re
text = '[email protected]中文QQ郵箱'
# 定義正則表示式,匹配目標字串中的電子郵箱
regexstr = '\[email protected]\w+\.[a-z]+'
# 將正則表示式編譯成 Pattern 物件
pattern = re.compile(regexstr)
# 匹配
match = pattern.match(text)
if match:
print(match.group())
print(match.start())
print(match.end())
print(match.span())
執行結果:
[email protected]
0
15
(0, 15)
search 方法
Search 方法用於查詢字串的任何位置,它只返回從左到右第一個匹配的結果,而不是查詢所有匹配的結果。
# search 方法示例
import re
text = 'one12twothree34four'
# 設定正則表示式查詢第一個數字串
regexstr = '\d+'
pattern = re.compile(regexstr)
# match 方法是從第一個字元開始匹配,這裡第一個字元不是數字,則返回 None
match = pattern.match(text)
print('pattern.match:')
print(match)
print('---'*10)
# search 方法是從左往右檢索,返回第一個匹配到的結果,這裡返回 12
match = pattern.search(text)
print('pattern.search:')
if match:
print(match.group())
print(match.span())
執行結果:
pattern.match:
None
------------------------------
pattern.search:
12
(3, 5)
findall 與 finditer 方法
上面的 match 和 search 方法都是一次性匹配,而有時需要獲取目標字串中所有匹配的結果,這需要使用 findall 或 finditer 方法。使用形式如下:
findall(string[, pos[, endpos]])
其中,string 是待匹配的字串,pos 和 endpos 是可選引數,指定字串的起始和終點位置,預設值分別是 0 和 len (字串長度)。
finditer 方法的行為跟 findall 的行為類似,也是搜尋整個字串,獲得所有匹配的結果,但是它返回一個順序訪問每一個匹配結果(Match 物件)的迭代器。
簡單講就是,findall 會把所有結果一次性返回,finditer 得用迴圈一個一個返回
import re
text = '你好[email protected]中文QQ郵箱'
# 定義正則表示式,匹配字串中的中文
regexstr = u'[\u4e00-\u9fa5]+'
pattern = re.compile(regexstr)
matchlist = pattern.findall(text)
if matchlist:
print(matchlist)
else:
print('None')
print('---'*10)
matchiter = pattern.finditer(text)
if matchiter:
print(matchiter)
for m in matchiter:
print('Match result:{}, postion: {}'.format(m.group(),m.span()))
else:
print('None')
執行結果:
['你好', '中文', '郵箱']
------------------------------
<callable_iterator object at 0x00000165B601D630>
Match result:你好, postion: (0, 2)
Match result:中文, postion: (17, 19)
Match result:郵箱, postion: (21, 23)
split 方法
split 方法按照能夠匹配的子串將字串分割後返回列表,它的使用形式如下:
split(string[, maxsplit])
其中,maxsplit 用於指定最大分割次數,不指定將全部分割。
import re
text = 'a,b;;c d ,;e'
# 正則表示式,字串前加 r,表示該字串是 raw string。
regexstr = r'[\,\;\s]+'
pattern = re.compile(regexstr)
match = pattern.split(text)
if match:
print(match)
else:
print('None')
執行結果:
['a', 'b', 'c', 'd', 'e']
sub 方法
sub 方法用於替換。它的使用形式如下:
sub(repl, string[, count])
- repl 可以是字串也可以是一個函式
- 如果 repl 是字串,則會使用 repl 去替換字串每一個匹配的子串,並返回替換後的字串,另外,repl 還可以使用 id 的形式來引用分組,但不能使用編號 0;
- 如果 repl 是函式,這個方法應當只接受一個引數(Match物件),並返回一個字串用於替換(返回的字串中不能再引用分組)。
- count 用於指定最多替換次數,不指定時全部替換。
import re
# 設定模式:兩個英文字元或數字的分組,中間用空格隔開
text = 'Hello 123, Hello 456'
regexstr = r'(\w+) (\w+)'
repl = 'Hello World'
pattern = re.compile(regexstr)
# 使用 'Hello World' 替換 'Hello 123' 和 'Hello 456'
res = pattern.sub(repl,text)
print(res)
print('---'*10)
# 引用分組
repl = r'\2 \1'
# regexstr 第一個括號裡匹配到的是 \1 ,第二個括號裡匹配到的是 \2
res = pattern.sub(repl,text)
print(res)
print('---'*10)
# 指定替換次數
def func(m):
return ('hi' + ' ' + m.group(2))
print(pattern.sub(func,text))
print(pattern.sub(func,text,1))
執行結果:
Hello World, Hello World
------------------------------
123 Hello, 456 Hello
------------------------------
hi 123, hi 456
hi 123, Hello 456
貪婪模式與非貪婪模式
- 貪婪模式,指的是整個表示式匹配成功的前提下,儘可能多的匹配(使用 * ),python 裡數量詞預設是貪婪的;
- 非貪婪模式,指的是整個表示式匹配成功的前提下,儘可能少的匹配(使用 *? )
# demo 1
import re
text = 'abbbbbbbbbbbbccccc'
regexStr1 = 'ab*'
regexStr2 = 'ab*?'
pattern = re.compile(regexStr1)
match = pattern.match(text)
print('貪婪模式:' + match.group())
print('---'*10)
pattern = re.compile(regexStr2)
match = pattern.match(text)
print('非貪婪模式:' + match.group())
執行結果:
貪婪模式:abbbbbbbbbbbb
------------------------------
非貪婪模式:a
# demo 2
import re
text = 'aa<div>test1</div>bb<div>test2</div>cc'
regexStr1 = '<div>.*</div>'
regexStr2 = '<div>.*?</div>'
pattern = re.compile(regexStr1)
m = pattern.search(text)
print(m.group())
print('---'*10)
pattern = re.compile(regexStr2)
m = pattern.search(text)
print(m.group())
執行結果:
<div>test1</div>bb<div>test2</div>
------------------------------
<div>test1</div>