myItems = re.findall('<div.*?class="content".*?title="(.*?)">(.*?)</div>',unicodePage,re.S)
“.*?”這種匹配方式,按理解應該是匹配任意字符0個或多個(re.S模式,“.”可以匹配“\n”),但是這個“?”總覺的在這兒是多餘的,既然不理解,就敲代碼試試:
import re
patern = re.compile('www\..*')
match1 = patern.match("www.baidu.com")
if match1:
print(match1.group())
else:
print("match1 don't match")
#output
>>> ==================RESTART =============================
>>>
www.baidu.com
這個結果,應該說是意料之中,加個“?”呢?
import re
patern = re.compile('www\..*?')
match1 = patern.match("www.baidu.com")
if match1:
print(match1.group())
else:
print("match1 don't match")
#output
>>> ==================RESTART =============================
>>>
www.
竟然是這個結果。。。“.?”一個字符都沒匹配,按“.”、“”、“?”的匹配理解,也就是“*”“?”均匹配前面字符0次,纔會是這個結果,可是爲啥就是0次了?
這就是正則表達式貪婪模式和非貪婪模式:
貪婪模式,總是嘗試匹配儘可能多的字符;
非貪婪模式則相反,總是嘗試匹配儘可能少的字符。
Python裏數量詞默認是貪婪的,這就解釋了第一個匹配實驗,輸出結果爲”www.baidu.com”(貪婪模式),也就是說第二個匹配實驗是非貪婪模式,僅僅因爲加了“?”,繼續實驗
import re
patern = re.compile('www\..?')
match1 = patern.match("www.baidu.com")
if match1:
print(match1.group())
else:
print("match1 don't match")
#output
>>> ==================RESTART =============================
>>>
www.b
此次匹配結果,顯然是貪婪模式。奇怪了,也就是“?”的特殊組合纔是非貪婪模式。
網上搜索得如下說明:
標準量詞修飾的子表達式,在可匹配可不匹配的情況下,總會先嚐試進行匹配,稱這種方式爲匹配優先,或者貪婪模式。此前介紹的一些量詞,“{m}”、“{m,n}”、“{m,}”、“?”、“*”和“+”都是匹配優先的。
一些NFA正則引擎支持忽略優先量詞,也就是在標準量詞後加一個“?”,此時,在可匹配可不匹配的情況下,總會先忽略匹配,只有在由忽略優先量詞修飾的子表達式,必須進行匹配才能使整個表達式匹配成功時,纔會進行匹配,稱這種方式爲忽略優先,或者非貪婪模式。忽略優先量詞包括“{m}?”、“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。
顯然“*?”的組合是非貪婪模式,猜想正確,原來如此啊。
還有就是, Python 中字符串前面加上 r 表示原生字符串,與大多數編程語言相同,正則表達式裏使用 "\" 作爲轉義字符,這就可能造成反斜槓困擾。假如你需要匹配文本中的字符 "\" ,那麼使用編程語言表示的正則表達式裏將需要4個反斜槓
"\\\\" :前兩個和後兩個分別用於在編程語言裏轉義成反斜槓,轉換成兩個反斜槓後再在正則表達式裏轉義成一個反斜槓。Python裏的原生字符串很好地解決了這個問題,這個例子中的正則表達式可以使用 r"\\" 表示。同樣,匹配一個數字的 "\\d" 可以寫成 r"\d" 。有了原生字符串,你再也不用擔心是不是漏寫了反斜槓,寫出來的表達式也更直觀。
\b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。 \B 匹配非單詞邊界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
match() 函數只檢測RE是不是在string的開始位置匹配, search() 會掃描整個 string 查找匹配, 也就是說 match() 只有在0位置匹配成功的話纔有返回,如果不是開始位置匹配成功的話, match() 就返回 none