Python 爬蟲十六式 - 第七式:正則的藝術

RE:用匹配來演繹編程的藝術

學習一時爽,一直學習一直爽python

  Hello,你們好,我是 Connor,一個個從無到有的技術小白。上一次咱們說到了 pyquery 今天咱們將迎來咱們數據匹配部分的最後一位重量級人物,也是編程語言中普及率最高的一個東西,它就是正則。正則長期以來佔據着編程新手的禁忌之地,你們對它是又愛又恨。今天,咱們將揭開他神祕的面紗,直面正則,並助你征服它,讓它成爲你的得力助手!正則表達式

1. 正則的介紹

  因爲正則並非 Python 所獨有的內容,本文大部分會以正則的角度來進行描述和講解,而不侷限於 re 庫,文章會穿插以 re 爲例,對正則的例子進行講解。算法

1.1 正則的起源

  想要完全掌握正則,就要從頭至尾的瞭解它。那麼正則是如何誕生的呢?這要追溯到上世紀人們對人類神經系統如何工做的早期研究。兩位神經生理學家研究出一種數學方式來描述這些神經網絡。具體叫什麼我就不說了。編程

  1956 年, 一位數學家在上面兩位神經生理學家早期工做的基礎上,發表了一篇標題爲「神經網事件的表示法」的論文,引入了正則表達式的概念。正則表達式就是用來描述他稱爲「正則集的代數」的表達式,所以採用「正則表達式」這個術語。緩存

  隨後他們發現能夠將這一研究成果普遍的應用於其它領域的研究。Ken Thompson 使用它來進行一些早期的計算搜索算法的一些研究,Ken Thompson 是 Unix 的主要發明人。正則表達式的第一個實用應用程序就是 Unix 中的 qed 編輯器。網絡

  而後,正則表達式在各類計算機語言或各類應用領域獲得了廣大的應用和發展,演變成爲目前計算機技術森林中的一隻形神美麗且聲音動聽的百靈鳥。到目前正則表達式在基於文本的編輯器和搜索工具中依然佔據這一個很是重要的地位。編程語言

  在最近的六十年中,正則表達式逐漸從模糊而深奧的數學概念,發展成爲在計算機各種工具和軟件包應用中的主要功能。不只僅衆多UNIX工具支持正則表達式,近二十年來,在 Windows 的陣營下,正則表達式的思想和應用在大部分 Windows 開發者工具包中獲得支持和嵌入應用!編輯器

  Windows 系列產品對正則表達式的支持發展到無與倫比的高度,目前幾乎全部 Microsoft 開發者和全部.NET語言均可以使用正則表達式。包括 Python、Java、JavaScript、Go 等非 Windows 系列的產品也對正則進行了支持,這無疑將正則變成了編程界的寵兒,能夠說得正則者得天下!函數

  因此,看到這裏是否是想要火燒眉毛地來學會正則了???讓咱們一塊兒來看看正則的概念:工具


1.2 正則的概念

  正則表達式是對字符串操做的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個「規則字符串」,這個「規則字符串」用來表達對字符串的一種過濾邏輯。

  Emmn… 看了這麼官方的描述仍是有些懵逼,說白了正則表達式就是經過一些指定好的特殊字符來代替某種字符。舉個例子:你們小時候都玩過撲克遊戲排火車,就是當你如今排的牌和前面的任意一張大小相同的時候,不管中間有多少,有什麼牌你均可以獲取這中間全部的牌。正則和這個相似,無視中間全部的東西,只要知足你這個規則,就能夠取出中間全部的內容!

  不知道個人例子夠不夠清晰,反正我絞盡腦汁也只想到了這一個比較像的例子,若是你有什麼更好的例子,能夠留言或評論,我將引用你的例子。

  說完了正則的概念,咱們再來看看正則有哪些特色吧!


1.3 正則的特色

  正則表達式有以下的特色:

  1. 靈活性、邏輯性和功能性很是的強;
  2. 能夠迅速地用極簡單的方式達到字符串的複雜控制。
  3. 適用於任何字符串

2. 正則表達式的基礎知識

  這裏日後都是基礎的東西,若是你以爲你都懂了想直接看Python的re庫請 點擊這裏>>

  既然大概瞭解了正則的歷史以及他的功能和特色,那麼讓咱們從正則表達式的基礎知識來開始學習吧。大多數教程都是從元字符開始的,可是他們忽略了一些最基礎的東西,這些東西對於初級運用或許沒有任何關係,可是當你要使用到高級用法的時候極可能會形成混亂,甚至是遺忘,因此咱們在開始前先來講一說正則的基礎知識:

2.1 字符串的位置講解

  在咱們的印象中,光標的位置就是在字符以後的,可是實際上在底層,光標指的並非當前字符的位置,而是光標前面的這個位置,如圖:

  真實的光標位置指的是光標以前的這個字母,是這個字母 e 的位置,因此在一個長度爲 n 的字符串中,總共有 n + 1 個位置。例如:

(0)a(1)b(2)c(3)
複製代碼

在這個長度爲 3 的字符串 abc 中,一共有 (0)(1)(2)(3)四個位置


2.2 佔有字符和零寬度

  可能如今說佔有字符和零寬度會讓你感受有些不知所措,可是當你看完後面的內以後再反過來看佔有字符和零寬度的時候你就會恍然大悟,將這兩個概念瞭然於心了。

  正則表達式匹配過程當中,若是子表達式匹配到東西,而並不是是一個位置,並最終保存到匹配的結果當中。這樣的就稱爲佔有字符,而只匹配一個位置,或者是匹配的內容並不保存到匹配結果中,這種就稱做零寬度,佔有字符是互斥的,零寬度是非互斥的。也就是一個字符,同一時間只能由一個子表達式匹配,而一個位置,卻能夠同時由多個零寬度的子表達式匹配。


2.3 正則表達式的控制權與傳動

  正則表達式由左到右依次進行匹配,一般狀況下是由一個表達式取得控制權,從字符串的的某個位置進行匹配,一個子表達式開始嘗試匹配的位置,是從前一個匹配成功的結束位置開始的。


3. 正則表達式的語法

3.1 正則表達式的元字符

  正則表達式的元字符是正則表達式的根本,全部的正則表達式都有元字符組成,正則表達式的元字符包括下列幾種:

3.1.1 基本元字符

字符 描述
. 匹配除換行符外的任意字符
* 匹配0個或多個符合表達式的字符
? 匹配0個或1個符合表達式的字符
+ 匹配1個或多個符合表達式的字符
[...] 匹配方括號內的任意字符
[^...] 匹配除方括號字符內的任意字符

3.1.2 轉義元字符

字符 描述
\ 用於轉義下一個字符
\A 僅匹配字符串的開頭
\b 匹配一個單詞的邊界
\B 匹配非單詞邊界
\cX 匹配指明的控制字符
\d 匹配一個數字,等價於[0-9]
\D 匹配一個非數字,等價於[^0-9]
\f 匹配一個換頁符,等價於\x0c和\cL
\n 匹配一個換行符,等價於\x0a和\cJ
\t 匹配一個製表符,等價於\x09和\cI
\r 匹配一個回車符,等價於\x0d和\cM
\s 匹配 一個不可見的字符
\S 匹配一個可見的字符
\v 匹配一個垂直製表符,等價於\x0b和\cK
\w 匹配包括下劃線的任何單詞字符
\W 匹配任何非單詞字符
\Z 僅匹配字符串的末尾
\xn 匹配轉移爲\xn的十六進制轉義字符
\un 匹配一個Unicode轉義字符

3.1.3 限定類元字符

字符 描述
{n} 匹配肯定的n個字符
{n,} 匹配至少n個字符
{n,m} 匹配至少n個字符,至多m個字符
| 或符號,用於鏈接多個表達式
- 範圍符,只能用於方括號中,如[a-z]
^ 匹配字符串的開頭,在方括號中表示取反
$ 匹配字符串的末尾
(parameter) 將括號內的內容進行匹配並分組
(?!parameter) 正向否認預查,匹配不是parameter的內容
(?=parameter) 正向確定預查,匹配是parameter的內容
(?:parameter) 匹配parameter獲取匹配結果
(?<=parameter) 反向確定預查,在任何匹配的paraemter處開始匹配字符串
(?<!parameter) 反向否認預查,在任何不符合parameter的地方開始匹配字符串

  只是在這裏向你羅列元字符你是不會懂如何使用正則的,請稍安勿躁,稍後咱們將以 Python 中的正則爲例,爲你們逐一展現各類元字符的用法。若是你比較急切,請點擊這裏來快速查看 re 庫的使用方法。瞭解了元字符,咱們再來認識一下可打印字符與非打印字符:


3.2 打印字符與非打印字符

3.2.1 打印字符

  如你所見,你在網上瀏覽到的全部的字符,這包括全部大寫和小寫字母、全部數字、全部標點符號和一些其餘符號。這些所有可見的字符都叫作可打印字符

3.2.2 非打印字符

  非打印字符也能夠是正則表達式的組成部分。下表列出了表示非打印字符的轉義序列:

字符 描述
\cx 匹配由x指明的控制字符。
\f 匹配一個換頁符。等價於 \x0c 和 \cL。
\n 匹配一個換行符。等價於 \x0a 和 \cJ。
\r 匹配一個回車符。等價於 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等價於 [^\f\n\r\t\v ]
\t 匹配一個製表符。等價於 \x09 和 \cI。
\v 匹配一個垂直製表符。等價於 \x0b 和 \cK。

  打印字符和非打印字符很是易懂,沒什麼難點,一筆帶過,下面咱們來看看運算符的優先級:


3.3 正則表達式運算符的優先級

  正則表達式從左到右進行計算,並遵循優先級順序,這與算術表達式很是相似。相同優先級的從左到右進行運算,不一樣優先級的運算先高後低。下表從最高到最低說明了各類正則表達式運算符的優先級順序:

運算符 描述
\ 轉義符
(), (?:), (?=), [] 圓括號和方括號
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, \任何元字符、任何字符 定位點和序列(即:位置和順序)
| 替換,"或"操做字符

  運算優先級很是相似於四則運算,沒什麼好說的,下面咱們來看看正則的匹配模式:


3.4 正則的匹配模式(表達式修飾符)

  正則表達式有時候不僅是須要使用簡單的正則語句,有時候還須要挑選合適的匹配模式(表達式修飾符),經過這些不一樣的匹配模式,能夠提高匹配的效率。正則的匹配模式如表:

模式 描述
/a 強制從字符串頭開頭進行匹配
/i 不區分大小寫匹配
/g 全局匹配
/m 多行匹配
/s 特殊字符匹配
/u 不重複匹配
/x 忽略模式中的空白

  到這裏就介紹完元字符了,若是你想直接看元字符的使用示例,請 點擊這裏>>

4. Python 的正則庫 -- re庫

  正則被廣大編程語言所支持,Python也不例外,Python 官方爲咱們封裝了 re 庫來支持正則的使用,下面咱們一塊兒來走進 Python 的 正則庫--re庫:

4.1 Python 中的正則匹配模式

  Python 的正則也是正則,因此它也有匹配模式。但這匹配模式又有些不一樣於正則的表達方式,咱們來看一看:

修飾符 描述
re.A 強制從字符串頭開始匹配
re.I 使匹配對大小寫不敏感
re.L 作本地化識別(locale-aware)匹配
re.M 多行匹配,影響 ^ 和 $
re.S 使 . 匹配包括換行在內的全部字符
re.U 根據Unicode字符集解析字符
re.X 該標誌經過給予你更靈活的格式以便你將正則表達式寫得更易於理解。

  能夠看到,匹配模式並再也不是 /* 來進行表示了,而是變成了 re.* 來進行表示了。


4.2 Python 中的正則經常使用方法

   Python 既然是一種語言,那麼它定然不會讓咱們傻敷敷的去使用,Python 爲咱們封裝好了方法,咱們來逐一看一下都有哪些方法吧:

4.2.1 compile()

re.compile(pattern, flags=0)
複製代碼

  這個方法用來將正則表達式進行編譯,返回一個Pattern對象。這麼說你必定仍是很懵逼,咱們來舉個例子:

import re
string = "Learning makes a good man better and ill man worse."
pattern = re.compile(r"m\w+")
result = pattern.findall(string)
print(result)
複製代碼

返回結果:

['makes', 'man', 'man']
複製代碼

  這樣就顯而易見了,先將正則表達式進行編譯,在下次使用的時候直接給編譯好的正則表達式一個字符串讓它去匹配就行了。這樣作的好處是提升了性能,若是你要處理大文檔,建議你這樣使用。

4.2.2 escape()

escape(pattern)
複製代碼

  這個方法能夠用來匹配除 ASCII字符,數字和特殊字符 ‘_’ 之外的全部字符。官方的說法就是不同,這個東西有時候真的挺讓人懵逼的,簡單來講,這個方法就是用來消除字符串中的任何特殊字符效果的。

  我舉個例子你就明白了。有時候問哦們在匹配網址的時候,由於 ‘.’ 是特殊字符,因此有些時候咱們沒法成功的進行匹配,咱們須要轉義後再進行匹配,大部分人的操做是這樣的:

import re
string = "www.baidu.com"
result = re.findall(r"baidu\.com", string)
print(result)
複製代碼

  這樣作確實能夠達到咱們想要的效果,可是對於想要玩騷操做的咱們來講,這樣太 Low 了,因此就有了這樣的方式:

import re
string = "www.biadu.com"
result = re.findall(re.escape("baidu.com"), string)
print(result)
複製代碼

  這樣一來,咱們就省去了寫轉義的麻煩步驟,案例中須要轉移的內容較少,可能看不出有什麼優點,可是當你匹配大量須要轉移的內容的時候,這樣作不只能夠省去打轉義字符的麻煩,並且也防止咱們漏打,錯打轉義字符。

  固然,你也要注意一點,使用這個方法會消除一切特殊字符的特殊效果,使用這種方法匹配具備必定的侷限性,不能再進行模糊匹配了,請按需使用。

4.2.3 findall()

findall(pattern,string,flags = 0複製代碼

  經過這個方法匹配出來的是字符串中全部非重疊匹配的列表。老規矩,舉個例子:

import re
string = "Learning makes a good man better and ill man worse."
result = re.findall(r'm\w+', string)
print(result)
複製代碼

運行結果:

['makes', 'man', 'man']
複製代碼

  

4.2.4 finditer()

finditer(pattern, string, flags=0)
複製代碼

  經過這個方法能夠將字符串中全部非重疊匹配上返回迭代器。對於每一個匹配,迭代器返回一個匹配對象,匹配結果中包含有空對象。

  簡單的說,就是返回一個可迭代的 Objct 對象,這是它和 findall() 方法惟一的區別。 咱們舉個例子:

import re
string = """ QQ郵箱: 123456789@qq.com 網易郵箱: 123456789@163.com 126郵箱: 123456789@126.com"""
ls = re.finditer(r"(\d+@\w+.com)", string, re.S)
print(type(ls))
for item in ls:
    print(item.group())
複製代碼

運行結果以下:

<class 'callable_iterator'>
123456789@qq.com
123456789@163.com
123456789@126.com
複製代碼

  生成的可迭代的 Object 對象中,內部對象都爲 SRE_Match 對象,該對象不可直接提取匹配的內容,須要經過 group() 方法來進行提取。

4.2.5 fullmatch()

fullmatch(pattern, string, flags=0)
複製代碼

  經過這個方法能夠用來判斷整個字符串是否匹配規則,若是符合規則則返回 match object。不符合則返回 None。舉個例子:

import re
string = """QQ郵箱: 123456789@qq.com"""
ls = re.fullmatch(r"QQ郵箱: 123456789@qq.com", string, re.S)
print(ls.group())
複製代碼

運行結果以下:

QQ郵箱:  123456789@qq.com
複製代碼

若是咱們隨意改變一下規則:

import re
string = """QQ郵箱: 123456789@qq.com"""
ls = re.fullmatch(r"QQ郵箱", string, re.S)
print(ls)
複製代碼

運行結果:

None
複製代碼

  能夠看得出,只有當整個字符串都符合匹配規則的時候才能匹配到東西,不然的話返回的是 None

4.2.6 match()

match(pattern, string, flags=0)
複製代碼

  使用這個方法能夠嘗試在字符串的開頭進行匹配,返回匹配對象,若是未找到匹配,則返回None。

  你應該注意到了,它是在字符串的開頭進行匹配的,若是你仍是不太清楚,那咱們接着來看例子:

import re
string = """QQ郵箱:123456789@qq.com"""
ls = re.match(r"QQ郵箱", string, re.S)
print(ls)
複製代碼

運行結果以下:

<_sre.SRE_Match object; span=(0, 4), match='QQ郵箱'>
複製代碼

由於咱們匹配的法則在開頭有,若是咱們換個規則的話:

import re
string = """QQ郵箱:123456789@qq.com"""
ls = re.match(r"\d+", string, re.S)
print(ls)
複製代碼

運行結果:

None
複製代碼

  按照咱們的想法它應該會匹配到@前面的一串數字吧?可是實際上它並無匹配到。這就是所謂的在字符串的開頭進行匹配。

4.2.7 purge()

  經過這個方法能夠清除正則表達式的緩存。這個方法貌似沒有啥好說的 …

4.2.8 search()

search(pattern, string, flags=0)
複製代碼

  搜索整個字符串以匹配符合規則的字符串,若是有則返回匹配對象,若是沒有則返回None。前面說的 match() 方法是隻在頭部進行匹配,而 search() 方法能夠在字符串中的任意位置進行匹配。例如:

import re
string = """QQ郵箱:123456789@qq.com"""
ls = re.search(r"\d+", string, re.S)
print(ls)
複製代碼

運行結果以下:

<_sre.SRE_Match object; span=(5, 14), match='123456789'>
複製代碼

  能夠看的出,沒有在字符串首部的字符也被匹配出來了。相比 match() 方法,search() 方法,findall() 方法要用的更多些。

4.2.9 split()

split(pattern,string,maxsplit = 0,flags = 0複製代碼

  看到這個方法我想你們第一時間想到的是字符串中的 split() 方法,恭喜你,猜對了,這個方法和 字符串中自帶的 split() 方法大同小異,這個方法增長的功能是能夠經過正則表達式來進行分割。例如:

首先舉一個都能理解的功能:

import re
string = """abc,123456789,@qq.com"""
ls = re.split(r",", string)
print(ls)
複製代碼

運行結果:

['abc', '123456789', '@qq.com']
複製代碼

  能夠看得出,如今的分割方法和 字符串中自帶的 split() 方法沒有什麼區別。下面咱們再看多出來的用法:

import re
string = """abc123456789@qq.com"""
ls = re.split(r"\d+", string)
print(ls)
複製代碼

運行結果:

['abc', '@qq.com']
複製代碼

  能夠看得出,該方法將 數字做爲分割依據進行了分割。若是你足夠細心的話,你會發現這個方法還有一個參數,叫 maxsplit 這個方法表明着最大分割次數。好比:

import re
string = """abc,123456789,@qq.com"""
ls = re.split(r",", string, 1)
print(ls)
複製代碼

運行結果以下:

['abc', '123456789,@qq.com']
複製代碼

  能夠看到它只進行了一次分割,maxsplit 就是用來控制分割次數的,分割從左到右依次進行分割。分割 maxsplit 次。

4.2.10 sub()

sub(pattern,repl,string,count = 0,flags = 0複製代碼

  將全部符合規則的字符串替換成 repl。最多替換 count個,默認所有替換。這是我我的認爲正則中除了 findall() 方法外最有用的方法了。批量替換超級有用!!!

  咳咳,激動了啊,下面咱們來講說這個方法的使用:

import re
string = """abc123456789@qq.com"""
ls = re.sub(r"456", "abc", string)
print(ls)
複製代碼

運行結果以下:

abc123abc789@qq.com
複製代碼

  一下就把字符串中的 456 給替換成 abc了,賊帶勁。用了這個方法你還想用 replace方法嗎?那個方法多傻,若是你不以爲,一會我會讓你認同個人觀點的。咱們先往下說,sub() 方法也有一個計數參數 count,咱們能夠經過給它賦值來指定替換個數。好比:

import re
string = """abc12abc67abc@qq.com"""
ls = re.sub(r"abc", "---", string, 2)
print(ls)
複製代碼

運行結果:

---12---67abc@qq.com
複製代碼

  在上面的程序中咱們指定了替換個數2,因此結果中只替換了兩個 abc,並無所有替換。若是不指定 count 參數的話,默認會進行所有替換。

4.2.11 subn()

subn(pattern,repl,string,count = 0,flags = 0複製代碼

  這個方法和 sub() 方法沒有什麼本質上的區別,惟一的不一樣就是它返回的是一個元組,這個元組包含有兩個內容,(1)替換後的字符串,(2)整個字符串中的替換次數。舉個例子:

import re
string = """abc12abc67abc@qq.com"""
ls = re.subn(r"abc", "---", string)
print(ls)
複製代碼

運行結果以下:

('---12---67---@qq.com', 3)
複製代碼

4.2.12 template()

template(pattern, flags=0)
複製代碼

  這個方法我查了不少資料,國內的網站並無幾我的寫這個方法的,可能有寫的,可是沒有用這個標題來進行發表吧,總之我沒有找到什麼詳細的資料,可是經過他的官方解釋:「編譯模板模式,返回模式對象」 能夠看得出它返回的是一個模式對象,和 re.compile() 方法相似,返回的都是一個模式對象。應該用法和 re.complie()類似。

  可是我查閱了國外的網站,你們有提到說發現這個函數,可是並無發現有什麼用處。你們說,可能這個函數並未實現預期想要的功能,或者這個函數出現了什麼問題而關閉了。因此只能暫時停留在這個狀態。固然平時咱們也用不到這個函數

  我經過本身的琢磨,本身的嘗試,發現這個函數大部分函數功能是和 compile() 方法相同的。好比:

import re
abc = re.template(r"abc", re.I)
string = "abcasdfadsfABCasdfabcasdfasdf"
result = abc.findall(string)
print(result)
複製代碼

運行結果以下:

['abc', 'ABC', 'abc']
複製代碼

可是最主要的問題是,該方法禁用全部的特殊字符,即re的元字符,好比:

import re
abc = re.template(r"\d+", re.I)
string = "abcasdfadsfABCasdfabcasdfasdf"
result = abc.findall(string)
print(result)
複製代碼

運行結果以下:

Traceback (most recent call last):
File "G:/Python/PyWin/test.py", line 2, in <module>
    abc = re.template(r"\d+", re.I)
    ....
複製代碼

這個狀況下就直接報錯了。因此我想不出來這個函數有什麼做用。之因此寫出來就當給你們開眼了。若是真的須要使用模板的話,仍是建議你們使用 re.compile() 方法來進行操做。

好了,這就是 Python 正則庫 re 中的全部函數了。下面我還有幾個內容要給你們說


4.3 re 中的 Pattern 對象

   這個Pattern 我爲何不在講方法以前說呢,就是怕大家不明白,讓我一會兒給弄暈了,因此我選擇在講完全部方法以後再說。這樣的話有些人不須要了解這麼深,直接找到他們想要的方法,直接去使用就行了。這樣也方便他們使用…

  好好,咱們如今來講 **Pattern **對象。那什麼是 Pattern 對象呢?若是你仔細看以前我寫的方法的話,你會發現幾乎每一個正則的方法裏都有一個 Pattern 參數 ,回想一下那個參數寫的什麼? 對,Pattern對象就是咱們編譯後的正則規則。

  以前咱們在講 re.compile() 方法的時候說過,這個方法返回的就是一個 Pattern對象。這個對象幾乎能夠執行 re 中的全部方法。是比較簡單的一個對象。相信你們均可以理解。我以爲也沒啥好說的了。


re 中的 Match 對象

  Emmn….說完了 Pattern對象咱們如今來講說 Match 對象。

  好的好的,我必定好好說這個….這個Match 對象呢,是 re構建的一個對象。咱們經過 match()fullmatch()search()fjinditer(),這幾種方法返回的都是 Match 對象。咱們來看看一個 Match 對象中都包含什麼:

<_sre.SRE_Match object; span=(3, 6), match='abc'>
複製代碼
  • span 指的是匹配到的字符串在字符串中的位置。例中的 3,6 分別是開始位置和結束位置。
  • match 指的是匹配到的內容

下面咱們來講說 Match 對象中經常使用的方法:

方法 解釋
end([group]) 獲取組的結束位置
expand(string) 將match對象中的字符串替換成指定字符串
group(index) 某個組匹配的結果
groupdict() 返回組名做爲key,每一個分組的匹配結果做爲value的字典
groups() 全部分組的匹配結果,每一個分組組成的結果以列表返回
start([group]) 獲取組的開始位置
span([group]) 獲取組的開始和結束位置

  這就是 Match 對象的全部內容了。仍是很容易掌握的嘛。


5. 正則表達式全部元字符的示例

  講完了正則表達式了,也講完了python中的 re庫,下面咱們來將以前說好的元字符的示例逐一展現出來:

5.1 基本元字符的示例

字符 描述
. 匹配除換行符外的任意字符
* 匹配0個或多個符合表達式的字符
? 匹配0個或1個符合表達式的字符
+ 匹配1個或多個符合表達式的字符
[...] 匹配方括號內的任意字符
[^...] 匹配除方括號字符內的任意字符

元字符 「.」 的示例:

import re
string = "abcdefghigklmnopqrstuvwxyz1234567890"
result = re.match(r".bc", string)
print(result.group())

運行結果:
abc
複製代碼

元字符 「*」 的示例:

import re
string = "abcdefghigklmnopqrstuvwxyz1234567890"
result = re.search(r"(a.*g)", string)
print(result.group())

運行結果:
abcdefg
複製代碼

元字符 「?」 的示例:

import re
string = "aaabcdefg"
result = re.search(r"a?b", string)
print(result.group())

運行結果:
ab
複製代碼

元字符 「+」 的示例:

import re
string = "aaabcdefg"
result = re.search(r"a+", string)
print(result.group())

運行結果:
aaa
複製代碼

元字符 「[…]」 的示例:

import re
string = "aaabcdefg123456789"
result = re.findall(r"[\D]+", string)
print(result)

運行結果:
['aaabcdefg']
複製代碼

元字符 「[^...]」 的示例:

import re
string = "aaabcdefg123456789"
result = re.findall(r"[^\d]+", string)
print(result)

運行結果:
['aaabcdefg']
複製代碼

5.2 轉義元字符的示例

字符 描述
\ 用於轉義下一個字符
\A 僅匹配字符串的開頭
\b 匹配一個單詞的邊界
\B 匹配非單詞邊界
\cX 匹配指明的控制字符
\d 匹配一個數字,等價於[0-9]
\D 匹配一個非數字,等價於0-9
\f 匹配一個換頁符,等價於\x0c和\cL
\n 匹配一個換行符,等價於\x0a和\cJ
\t 匹配一個製表符,等價於\x09和\cI
\r 匹配一個回車符,等價於\x0d和\cM
\s 匹配 一個不可見的字符
\S 匹配一個可見的字符
\v 匹配一個垂直製表符,等價於\x0b和\cK
\w 匹配包括下劃線的任何單詞字符
\W 匹配任何非單詞字符
\Z 僅匹配字符串的末尾
\xn 匹配轉移爲\xn的十六進制轉義字符
\un 匹配一個Unicode轉義字符

元字符 「\」 的示例:

import re
string = "aaabcdefg123456789"
result = re.findall(r"\d+", string)
print(result)

運行結果:
['123456789']
複製代碼

元字符 「\A」 的示例

import re
string = "aaabcdefg123456789"
result = re.findall(r"\A\w", string)
print(result)

運行結果:
['a']
複製代碼

元字符 「\b」 的示例

import re
string = "aaabcdefg123456789"
result = re.findall(r"\b\w{5}", string)
print(result)

運行結果:
['aaabc']
複製代碼

元字符 「\B」 的示例

import re
string = "I'm the king of the world"
result = re.findall(r"\B\w+", string)
print(result)

運行結果:
['he', 'ing', 'f', 'he', 'orld']
複製代碼

元字符 「\d」 的示例

import re
string = "abcdefg1234567"
result = re.findall(r"\d+", string, re.S)
print(result)

運行結果:
['1234567']
複製代碼

元字符 「\D」 的示例

import re
string = "abcdefg1234567"
result = re.findall(r"\D+", string, re.S)
print(result)

運行結果:
['abcdefg']
複製代碼

元字符 「\f」 的示例

import re
string = "abcdefg\f1234567"
result = re.findall(r"\f", string, re.S)
print(result)

運行結果:
['\x0c']
複製代碼

元字符 「\n」 的示例

import re
string = "abcdefg\n1234567"
result = re.findall(r"\n\d+", string, re.S)
print(result)

運行結果:
['\n1234567']
複製代碼

元字符 「\t」 的示例

import re
string = "abcdefg\t1234567"
result = re.findall(r"\t", string, re.S)
print(result)

運行結果:
['\t']
複製代碼

元字符 「\r」 的示例

import re
string = """abcdefg\r1234567"""
print(string)
result = re.findall(r"\r", string, re.S)
print(result)

運行結果:
1234567
['\r']
複製代碼

元字符 「\s」 的示例

import re
string = """abcdefg\n1234567"""
result = re.findall(r"\s", string, re.S)
print(result)

運行結果:
['\n']
複製代碼

元字符 「\S」 的示例

import re
string = """abcdefg\n1234567"""
result = re.findall(r"\S+", string, re.S)
print(result)

運行結果:
['abcdefg', '1234567']
複製代碼

元字符 「\w」 的示例

import re
string = """I_m the king of the world"""
result = re.findall(r"\w+", string, re.S)
print(result)

運行結果:
['I_m', 'the', 'king', 'of', 'the', 'world']
複製代碼

元字符 「\W」 的示例

import re
string = """I'm the king of the world"""
result = re.findall(r"\W+", string, re.S)
print(result)

運行結果:
["'", ' ', ' ', ' ', ' ', ' ']
複製代碼

元字符 「\Z」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\w{2}\Z", string, re.S)
print(result)

運行結果:
['yz']
複製代碼

元字符 「\xn」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\x77", string, re.S)
print(result)

運行結果:
['w']
複製代碼

元字符 「\un」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\u0077", string, re.S)
print(result)

運行結果:
['w']
複製代碼

5.3 限定類元字符的示例

字符 描述
{n} 匹配肯定的n個字符
{n,} 匹配至少n個字符
{n,m} 匹配至少n個字符,至多m個字符
| 或符號,用於鏈接多個表達式
- 範圍符,只能用於方括號中,如[a-z]
^ 匹配字符串的開頭,在方括號中表示取反
$ 匹配字符串的末尾
(parameter) 將括號內的內容進行匹配並分組
(?!parameter) 正向否認預查,匹配不是parameter的內容
(?=parameter) 正向確定預查,匹配是parameter的內容
(?:parameter) 匹配parameter獲取匹配結果
(?<=parameter) 反向確定預查,在任何匹配的paraemter處開始匹配字符串
(?<!parameter) 反向否認預查,在任何不符合parameter的地方開始匹配字符串

元字符 「{n}」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w{2}", string, re.S)
print(result)

運行結果:
['uvw']
複製代碼

元字符 「{n,}」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w{3,}", string, re.S)
print(result)

運行結果:
['uvwxyz']
複製代碼

元字符 「{n,m}」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w{1,3}", string, re.S)
print(result)

運行結果:
['uvwx']
複製代碼

元字符 「|」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u\w|x\w", string, re.S)
print(result)

運行結果:
['uv', 'xy']
複製代碼

元字符 「-」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"[a-z]+", string, re.S)
print(result)

運行結果:
['uvwxyz']
複製代碼

元字符 「^」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"[^1-9]+", string, re.S)
print(result)

運行結果:
['uvwxyz']
複製代碼

元字符 「$」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"\w{3}$", string, re.S)
print(result)

運行結果:
['xyz']
複製代碼

元字符 「(parameter)」 的示例

import re
string = """uvwxyz"""
result = re.findall(r"u(\w{2})x(\w{2})", string, re.S)
print(result)

運行結果:
[('vw', 'yz')]
複製代碼

元字符 「(?=parameter)」 的示例

import re
string = """COD4 COD6 COD8"""
result = re.findall(r"COD.(?=4)", string, re.S) #匹配.=4的字符串COD
print(result)

運行結果:
['COD4']
複製代碼

元字符 「(?!parameter)」 的示例

import re
string = """COD4 COD6 COD8 """
result = re.findall(r"COD.(?!4)", string, re.S) # 匹配 .!=4的字符串
print(result)

運行結果:
['COD6', 'COD8']
複製代碼

元字符 「(?:parameter)」 的示例

import re
string = """COD4COD6COD8"""
result = re.findall(r".*?(?:4)", string, re.S) # 匹配獲取參數爲4的字符串
print(result)

運行結果:
['COD4']
複製代碼

元字符 「(?<=parameter)」 的示例

import re
string = """COD4 COD6 COD8 """
result = re.findall(r"COD.(?<=4)", string, re.S) # 從右向左匹配.=4的字符串
print(result)

運行結果:
['COD4']
複製代碼

元字符 「(?<!parameter)」 的示例

import re
string = """COD4 COD6 COD8 """
result = re.findall(r"COD.(?<!4)", string, re.S) # 從右向左匹配.!=4的字符串
print(result)

運行結果:
['COD6', 'COD8']
複製代碼

  到這裏咱們就把正則的全部元字符的示例就都演示完了。我所演示的是最基礎的用法,若是真的想要使用高級的用法,仍是要本身多進行嘗試,多練習。練習的多了使用正則纔會信手拈來。


下期預告

  你看你說了這麼多,又是訪問網頁,又是獲取數據的,說了半天咱們仍是不知道怎麼用。我會只是單獨的給大家說這麼簡單嗎?固然會有練習的啦。敬請期待下一期:Python 爬蟲十六式 - 第八式:實例解析-全書網!咱們經過全書網來讓你一下吸取前面的知識。

  好了,這就是今天的內容了,不知道你又學會了多少呢?我是Connor,一個從無到有的技術小白,願你在前進的道路上堅持不懈!

學習一時爽,一直學習一直爽!

系列文章

Python 爬蟲十六式 - 第一式:HTTP協議 >>>
Python 爬蟲十六式 - 第二式:urllib 與 urllib3 >>>
Python 爬蟲十六式 - 第三式:Requests的用法 >>>
Python 爬蟲十六式 - 第四式: 使用Xpath提取網頁內容 >>>
Python 爬蟲十六式 - 第五式:BeautifulSoup,美味的湯 >>>
Python 爬蟲十六式 - 第六式:JQuery的假兄弟-pyquery >>>
Python 爬蟲十六式 - 第八式:實例解析-全書網 >>>

相關文章
相關標籤/搜索