Python爬蟲(二十三)
學習Python爬蟲過程中的心得體會以及知識點的整理,方便我自己查找,也希望可以和大家一起交流。
—— Re庫與正則表達式的細節解析 ——
1. 麻煩的反斜槓
上一篇中我們已經提到了,正則表達式使用 ‘’ 字符來使得一些普通的字符擁有特殊的能力(例如 \d表示匹配任何十進制數字),或者剝奪一些特殊字符的能力(例如 [ 表示匹配左方括號 ‘[’)。這會跟 Python字符串中實現相同功能的字符發生衝突。
例如使用正則表達式匹配字符串 ‘\section’。因爲反斜槓作爲需要匹配的特殊字符,所以你需要再它前邊加多一個反斜槓來剝奪它的特殊功能。所以我們會把正則表達式的字符寫成 '\\section'
。
但不要忘了,Python 在字符串中同樣使用反斜槓來表示特殊意義。因此,如果我們想將 ‘\section’ 完整地傳給 re.compile(),我們需要再次添加兩個反斜槓:
匹配字符 | 匹配階段 |
---|---|
\section | 需要匹配的字符串 |
\section | 正則表達式使用 '\\' 表示匹配字符 '\' |
“\\section” | Python 字符串也使用 '\\' 表示字符 '\' |
因此,爲了匹配反斜槓這個字符,我們需要在字符串中使用四個反斜槓纔行。所以,在正則表達式中頻繁地使用反斜槓,會造成反斜槓風暴,進而導致你的字符串極其難懂。
解決方法是使用 Python 的原始字符串來表示正則表達式(就是在字符串前邊加上 r):
正則字符串 | 原始字符串 |
---|---|
“ab*” | r"ab*" |
“\\section” | r"\section" |
“\w+\s+\1” | r"\w+\s+\1" |
下邊的例子中,我們故意不寫表示原始字符串的 'r'
,結果確實大相庭徑:
p = re.compile('\bclass\b')
print(p.search('no class at all'))
print(p.search('\b' + 'class' + '\b'))
結果如圖:
強烈建議使用原始字符串來表達正則表達式。
2. 零寬斷言
有些元字符它們不匹配任何字符,只是簡單地表示成功或失敗,因此這些字符也稱之爲零寬斷言。例如 \b
表示當前位置位於一個單詞的邊界,但 \b
並不能改變位置。因此,零寬斷言不應該被重複使用,因爲 \b
並不會修改當前位置,所以 \b\b
跟 \b
是沒什麼兩樣的。
例如: abc
匹配完 a 之後,匹配當前位置就會移動,才能繼續匹配 b,依次類推。但是 \babc
的話,\b
表示當前位置在單詞的邊界(單詞的第一個字母或者最後一個字母),這時候當前位置不會發生改變,接着將 a 與當前位置的字符進行匹配。