Python爬蟲(二十二)
學習Python爬蟲過程中的心得體會以及知識點的整理,方便我自己查找,也希望可以和大家一起交流。
—— Re庫應用詳解 ——
文章目錄
1.正則表達式的表示類型
- raw string類型(原生字符串類型)
- re庫採用raw string類型表示正則表達式,表示爲:r ’ text ’
- 例如:r ’ [19]\d{5} ’ r ‘\d{3} \d{8}|\d{4}\d{7}’
- raw string 是不包含轉義符的字符串
- string 類型,更繁瑣,要轉義
2.Re庫的主要功能函數
函數 | 說明 |
---|---|
re.search() | 遍歷字符串,找到正則表達式匹配的第一個位置 【注1】 ,返回match對象 |
re.match() | 判斷一個正則表達式是否從開始處匹配一個字符串 【注1】 ,返回match對象 |
re.findall() | 遍歷字符串,找到正則表達式匹配的所有位置,並以列表的形式返回 |
re.split() | 將一個字符串按照正則表達式匹配結果進行分割。返回列表類型 |
re.finditer() | 遍歷字符串,找到正則表達式匹配的所有位置,並以迭代器的形式返回,每個迭代元素是match對象 |
re.sub() | 在一個字符串中替換所有匹配正則表達式的子串,返回替換後的字符串 |
【注1】:如果沒有找到任何匹配的話,match() 和 search() 會返回 None ;如果匹配成功,則會返回一個匹配對象 (match object) ,包含所有匹配的信息:例如從哪兒開始,到哪兒結束,匹配的子字符串等等。
2.1 match()
例如:
import re
p = re.compile('[a-z]+')
print(p)
p.match("")
print(p.match(""))
結果如圖:
因爲 +
表示將前面的(A-Z)匹配一次或者多次,所以空字符串不能被匹配。因此,match() 返回 None
我們換一個匹配字符串:
m = p.match('fishc')
print(m)
結果如圖:
可以看到匹配對象包含了很多方法和屬性,以下幾個是最重要的:
方法 | 功能 |
---|---|
group() | 返回匹配的字符串 |
start() | 返回匹配的開始位置 |
end() | 返回匹配的結束位置 |
span() | 返回一個元組表示匹配位置(開始,結束) |
例如:
由於 match() 只檢查正則表達式是否在字符串的起始位置匹配,所以 start() 總是返回 0。
2.2 search()
有兩個方法可以返回所有的匹配結果,一個是 findall(),另一個是 finditer()。
2.3 findall()
findall() 返回的是一個列表:
p = re.compile('\d+')
p.findall('3個香蕉,15個蘋果,7個人怎麼分?')
結果如圖:
2.4 finditer()
findall() 需要在返回前先創建一個列表,而 finditer() 則是將匹配對象作爲一個迭代器返回:
iterator = p.finditer('3個香蕉,15個蘋果,7個人怎麼分?')
print(iterator)
for match in iterator:
print(match.span())
結果如圖:
3. 編譯標誌
編譯標誌讓你可以修改正則表達式的工作方式。在 re 模塊下,編譯標誌均有兩個名字:完整名和簡寫,例如 IGNORECASE 簡寫是 I。另外,多個標誌還可以同時使用(通過“|
”),如:re.I | re.M
就是同時設置 I 和 M 標誌。
下邊列舉一些支持的編譯標誌:
標誌 | 含義 |
---|---|
ASCII, A | 使得轉義符號如 \w,\b,\s 和 \d 只能匹配 ASCII 字符 |
DOTALL, S | 使得 . 匹配任何符號,包括換行符 |
IGNORECASE, I | 匹配的時候不區分大小寫 |
LOCALE,,L | 支持當前的語言(區域)設置 |
MULTILINE, M | 多行匹配,影響 ^ 和 $ |
VERBOSE,X (for ‘extended’) | 啓用詳細的正則表達式 |
A——ASCII
使得 \w,\W,\b,\B,\s 和 \S 只匹配 ASCII 字符,而不匹配完整的 Unicode 字符。這個標誌僅對 Unicode 模式有意義,並忽略字節模式。
S——DOTALL
使得 .
可以匹配任何字符,包括換行符。如果不使用這個標誌,.
將匹配除了換行符的所有字符。
I——IGNORECASE
字符類和文本字符串在匹配的時候不區分大小寫。
例如:正則表達式 [A-Z] 也將會匹配對應的小寫字母,像banana 可以匹配 Banana,BANANA 或 bananA 等。如果你不設置 LOCALE,則不會考慮語言(區域)設置這方面的大小寫問題。
L——LOCALE
使得 \w,\W,\b 和 \B 依賴當前的語言(區域)環境,而不是 Unicode 數據庫。
區域設置是 C 語言的一個功能,主要作用是消除不同語言之間的差異。
例如:你正在處理的是法文文本,你想使用 \w+
來匹配單詞,但是 \w
只是匹配 [A-Za-z] 中的單詞,並不會匹配 é
或 ç
。如果你的系統正確的設置了法語區域環境,那麼 C 語言的函數就會告訴程序é
或 ç
也應該被認爲是一個字符。當編譯正則表達式的時候設置了 LOCALE 的標誌,\w+ 就可以識別法文了,但速度多少會受到影響。
M——MULTILINE
通常 ^ 只匹配字符串的開頭,而 $ 則匹配字符串的結尾。當這個標誌被設置的時候,^ 不僅匹配字符串的開頭,還匹配每一行的行首;& 不僅匹配字符串的結尾,還匹配每一行的行尾。
X——VERBOSE
這個標誌使你的正則表達式可以寫得更好看和更有條理,因爲使用了這個標誌,空格會被忽略(除了出現在字符類中和使用反斜槓轉義的空格);
這個標誌同時允許你在正則表達式字符串中使用註釋,# 符號後邊的內容是註釋,不會遞交給匹配引擎(除了出現在字符類中和使用反斜槓轉義的 #)。
下邊是使用 re.VERBOSE 的例子,大家看下正則表達式的可讀性是不是提高了不少:
charref = re.compile(r"""
&[#] # 開始數字引用
(
0[0-7]+ # 八進制格式
| [0-9]+ # 十進制格式
| x[0-9a-fA-F]+ # 十六進制格式
)
; # 結尾分號
""", re.VERBOSE)
如果沒有設置 VERBOSE 標誌,那麼同樣的正則表達式會寫成:
charref = re.compile("&#(0[0-7]+|[0-9]+|x[0-9a-fA-F]+);")
哪個可讀性更大呢?