首頁 > 軟體

Pyhton爬蟲知識之正規表示式詳解

2022-04-01 13:02:14

前言

在爬蟲的開發中,需要把有用的資訊從一大段文字中提取出來,正規表示式是提取資訊的方法之一。

1、正規表示式基礎

正規表示式(Regular Expression)是一段字串,它可以表示一段有規律的資訊。Python自帶一個正規表示式模組 - re,通過這個模組可以查詢、提取、替換一段有規律的資訊。在程式開發中,要讓計算機程式從一大段文字中找到需要的內容,就可以使用正規表示式來實現。

使用正規表示式有如下步驟:

(1)尋找規律

(2)使用正則符號表示規律

(3)提取資訊

2、正規表示式的基本符號

2.1 點號 “.”

一個點號可以代替除了換行符以外的任何一個字元,包括但不限於英文字母、數位、漢字、英文標點符號和中文標點符號。

2.2 星號 “*”

一個星號可以表示它前面的一個子表示式(普通字元、另一個或幾個正規表示式符號)0次到無限次。

2.3 問號 “?”

一個問號可以表示它前面的子表示式0次或者1次。注意,這裡的問號是英文問號。

2.4 反斜槓 “”

反斜槓在正規表示式裡面不能單獨使用,甚至在整個 Python 裡都不能單獨使用。反斜槓需要和其他的字元配合使用來把特殊符號變成普通符號,把普通符號變成特殊符號:

2.5 數位 “d”

正規表示式裡面使用 “d” 來表示一位數位。為什麼要用字母d呢?因為d是英文“digital(數位)”的首字母。強調一下,“d”雖然是由反斜槓和字母d構成的,但是要把“d”看成一個正規表示式符號整體。

2.6 小括號 “()”

小括號可以把括號裡面的內容提取出來。

3、Python中使用正規表示式

Python 已經自帶了一個功能非常強大的正規表示式模組。使用這個模組可以非常方便地通過正規表示式來從一大段文字中提取有規律的資訊。Python的正規表示式模組名字為“re”,也就是“regularexpression”的首字母縮寫。在Python中需要首先匯入這個模組再進行使用。匯入的語句為:

import re # pycharm 如果報錯 Alt+Enter 自動匯入即可

下面我們來介紹一下常用的API:

3.1 findall

Python的正規表示式模組包含一個findall方法,它能夠以列表的形式返回所有滿足要求的字串。

def findall(pattern, string, flags=0):
    """Return a list of all non-overlapping matches in the string.

    If one or more capturing groups are present in the pattern, return
    a list of groups; this will be a list of tuples if the pattern
    has more than one group.

    Empty matches are included in the result."""
    return _compile(pattern, flags).findall(string)

pattern表示正規表示式,string表示原來的字串,flags表示一些特殊功能的標誌。

findall 的結果是一個列表,包含了所有的匹配到的結果。如果沒有匹配到結果,就會返回空列表:

content = '我的電腦密碼是:123456,我的手機密碼是:888888,我的家門密碼是:000000,勿忘!'

pwd_list = re.findall('是:(.*?),', content)
machine_list = re.findall('我的(.*?)密碼是:', content)
name_list = re.findall('名字是(.*?),', content)
print('所有密碼為:{}'.format(pwd_list))
print('所屬為:{}'.format(machine_list))
print('使用者姓名為:{}'.format(name_list))

結果中很明顯沒有匹配到結果的為空 List 。這裡還有一個變化:在匹配密碼的時候,如左圖會少一個。原因就出在匹配上面,我的匹配規則為:'是:(.*?),',必須嚴格滿足這個格式的文字的中間密碼部分才能被提取出來,重點就是後面的 , ,如右圖加上了 ,勿忘! 就使得前面的文字滿足匹配規則,從而進行提取:

當需要提取某些內容的時候,使用小括號將這些內容括起來,這樣才不會得到不相干的資訊。如果包含多個 “(.*?)” 如下圖所示,返回的仍然是一個列表,但是列表裡面的元素變為了元組,元組裡面的第1個元素是賬號,第2個元素為密碼:

函數原型中有一個flags引數。這個引數是可以省略的;當不省略的時候,具有一些輔助功能,例如忽略大小寫、忽略換行符等。這裡以忽略換行符為例來進行說明:

常用的引數:

re.I
    IGNORECASE
    忽略字母大小寫

re.L
    LOCALE
    影響 “w, “W, “b, 和 “B,這取決於當前的在地化設定。

re.M
    MULTILINE
    使用本標誌後,‘^’和‘$’匹配行首和行尾時,會增加換行符之前和之後的位置。

re.S
    DOTALL
    使 “.” 特殊字元完全匹配任何字元,包括換行;沒有這個標誌, “.” 匹配除了換行符外的任何字元。

re.X
    VERBOSE
    當該標誌被指定時,在 RE 字串中的空白符被忽略,除非該空白符在字元類中或在反斜槓之後。
    它也可以允許你將註釋寫入 RE,這些註釋會被引擎忽略;
    註釋用 “#”號 來標識,不過該符號不能在字串或反斜槓之後。

參考:Python 正規表示式 flags 引數

3.2 serach

search() 的用法和 findall() 的用法一樣,但是 search() 只會返回第1個滿足要求的字串。一旦找到符合要求的內容,它就會停止查詢。對於從超級大的文字裡面只找第1個資料特別有用,可以大大提高程式的執行效率。

def search(pattern, string, flags=0):
    """Scan through string looking for a match to the pattern, returning
    a Match object, or None if no match was found."""
    return _compile(pattern, flags).search(string)

對於結果,如果匹配成功,則是一個正規表示式的物件,要得到匹配到的結果,則需要通過.group()這個方法來獲取裡面的值;如果沒有匹配到任何資料,就是 None:

只有在.group()裡面的引數為1的時候,才會把正規表示式裡面的括號中的結果列印出來。
.group()的引數最大不能超過正規表示式裡面括號的個數。引數為1表示讀取第1個括號中的內容,引數為2表示讀取第2個括號中的內容,以此類推:

3.3 “.* ” 和 “.*?” 的區別

在爬蟲開發中,.*? 這3個符號大多數情況下一起使用。

  • 點號表示任意非換行符的字元,星號表示匹配它前面的字元0次或者任意多次。所以“.*”表示匹配一串任意長度的字串任意次。
  • 這個時候必須在“.*”的前後加其他的符號來限定範圍,否則得到的結果就是原來的整個字串。
  • 如果在“.*”的後面加一個問號,變成 “.*?”,那麼可以得到什麼樣的結果呢?問號表示匹配它前面的符號0次或者1次。於是 “.*?” 的意思就是匹配一個能滿足要求的最短字串。

使用“(.*)”得到的是隻有一個元素的列表,裡面是一個很長的字串。

使用“(.*?)”得到的結果是包含3個元素的列表,每個元素直接對應原來文字中的每個密碼。

總結:

①“.*”:貪婪模式,獲取最長的滿足條件的字串。②“.*?”:非貪婪模式,獲取最短的能滿足條件的字串。

4、正規表示式提取技巧

4.1 不需使用 compile

def findall(pattern, string, flags=0):
    """Return a list of all non-overlapping matches in the string.

    If one or more capturing groups are present in the pattern, return
    a list of groups; this will be a list of tuples if the pattern
    has more than one group.

    Empty matches are included in the result."""
    return _compile(pattern, flags).findall(string)

def compile(pattern, flags=0):
    "Compile a regular expression pattern, returning a Pattern object."
    return _compile(pattern, flags)

使用re.compile()的時候,程式內部呼叫的是_compile()方法;當使用re.finall()的時候,在模組內部自動先呼叫了_compile()方法,再呼叫findall()方法。re.findall()自帶re.compile()的功能,所以沒有必要使用re.compile()。

4.2 先抓大再抓小

一些無效內容和有效內容可能具有相同的規則。這種情況下很容易把有效內容和無效內容混在一起,如下面這段文字:

有效使用者:姓名: 張三姓名: 李四姓名: 王五無效使用者:姓名: 不知名的小蝦米姓名: 隱身的張大俠

有效使用者和無效使用者的名字前面都以“姓名: ”開頭,如果使用“姓名: (.*?)n”來進行匹配,就會把有效資訊和無效資訊混在一起,難以區分:

要解決這個問題,就需要使用先抓大再抓小的技巧。先把有效使用者這個整體匹配出來,再從有效使用者裡面匹配出人名:

4.3 括號內和括號外

在上面的例子中,括號和“.*?”都是一起使用的,因此可能會有讀者認為括號內只能有這3種字元,不能有其他普通的字元。但實際上,括號內也可以有其他字元,對匹配結果的影響結果如下:

其實不難理解,只需要記住:"按照匹配規則查詢,括號內的被提取" 就可以了!

總結

到此這篇關於Pyhton爬蟲知識之正規表示式的文章就介紹到這了,更多相關Pyhton爬蟲正規表示式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com