Pyhton爬蟲知識之正則表達式詳解
前言
在爬蟲的開發(fā)中,需要把有用的信息從一大段文本中提取出來,正則表達式是提取信息的方法之一。
1、正則表達式基礎(chǔ)
正則表達式(Regular Expression)是一段字符串,它可以表示一段有規(guī)律的信息。Python自帶一個正則表達式模塊 - re,通過這個模塊可以查找、提取、替換一段有規(guī)律的信息。在程序開發(fā)中,要讓計算機程序從一大段文本中找到需要的內(nèi)容,就可以使用正則表達式來實現(xiàn)。
使用正則表達式有如下步驟:
(1)尋找規(guī)律
(2)使用正則符號表示規(guī)律
(3)提取信息
2、正則表達式的基本符號
2.1 點號 “.”
一個點號可以代替除了換行符以外的任何一個字符,包括但不限于英文字母、數(shù)字、漢字、英文標點符號和中文標點符號。
2.2 星號 “*”
一個星號可以表示它前面的一個子表達式(普通字符、另一個或幾個正則表達式符號)0次到無限次。
2.3 問號 “?”
一個問號可以表示它前面的子表達式0次或者1次。注意,這里的問號是英文問號。
2.4 反斜杠 “\”
反斜杠在正則表達式里面不能單獨使用,甚至在整個 Python 里都不能單獨使用。反斜杠需要和其他的字符配合使用來把特殊符號變成普通符號,把普通符號變成特殊符號:
2.5 數(shù)字 “\d”
正則表達式里面使用 “\d” 來表示一位數(shù)字。為什么要用字母d呢?因為d是英文“digital(數(shù)字)”的首字母。強調(diào)一下,“\d”雖然是由反斜杠和字母d構(gòu)成的,但是要把“\d”看成一個正則表達式符號整體。
2.6 小括號 “()”
小括號可以把括號里面的內(nèi)容提取出來。
3、Python中使用正則表達式
Python 已經(jīng)自帶了一個功能非常強大的正則表達式模塊。使用這個模塊可以非常方便地通過正則表達式來從一大段文字中提取有規(guī)律的信息。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 的結(jié)果是一個列表,包含了所有的匹配到的結(jié)果。如果沒有匹配到結(jié)果,就會返回空列表:
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))
結(jié)果中很明顯沒有匹配到結(jié)果的為空 List 。這里還有一個變化:在匹配密碼的時候,如左圖會少一個。原因就出在匹配上面,我的匹配規(guī)則為:'是:(.*?),',必須嚴格滿足這個格式的文本的中間密碼部分才能被提取出來,重點就是后面的 , ,如右圖加上了 ,勿忘! 就使得前面的文本滿足匹配規(guī)則,從而進行提取:
當需要提取某些內(nèi)容的時候,使用小括號將這些內(nèi)容括起來,這樣才不會得到不相干的信息。如果包含多個 “(.*?)” 如下圖所示,返回的仍然是一個列表,但是列表里面的元素變?yōu)榱嗽M,元組里面的第1個元素是賬號,第2個元素為密碼:
函數(shù)原型中有一個flags參數(shù)。這個參數(shù)是可以省略的;當不省略的時候,具有一些輔助功能,例如忽略大小寫、忽略換行符等。這里以忽略換行符為例來進行說明:
常用的參數(shù):
re.I
IGNORECASE
忽略字母大小寫re.L
LOCALE
影響 “w, “W, “b, 和 “B,這取決于當前的本地化設(shè)置。re.M
MULTILINE
使用本標志后,‘^’和‘$’匹配行首和行尾時,會增加換行符之前和之后的位置。re.S
DOTALL
使 “.” 特殊字符完全匹配任何字符,包括換行;沒有這個標志, “.” 匹配除了換行符外的任何字符。re.X
VERBOSE
當該標志被指定時,在 RE 字符串中的空白符被忽略,除非該空白符在字符類中或在反斜杠之后。
它也可以允許你將注釋寫入 RE,這些注釋會被引擎忽略;
注釋用 “#”號 來標識,不過該符號不能在字符串或反斜杠之后。
3.2 serach
search() 的用法和 findall() 的用法一樣,但是 search() 只會返回第1個滿足要求的字符串。一旦找到符合要求的內(nèi)容,它就會停止查找。對于從超級大的文本里面只找第1個數(shù)據(jù)特別有用,可以大大提高程序的運行效率。
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)
對于結(jié)果,如果匹配成功,則是一個正則表達式的對象,要得到匹配到的結(jié)果,則需要通過.group()這個方法來獲取里面的值;如果沒有匹配到任何數(shù)據(jù),就是 None:
只有在.group()里面的參數(shù)為1的時候,才會把正則表達式里面的括號中的結(jié)果打印出來。
.group()的參數(shù)最大不能超過正則表達式里面括號的個數(shù)。參數(shù)為1表示讀取第1個括號中的內(nèi)容,參數(shù)為2表示讀取第2個括號中的內(nèi)容,以此類推:
3.3 “.* ” 和 “.*?” 的區(qū)別
在爬蟲開發(fā)中,.*? 這3個符號大多數(shù)情況下一起使用。
- 點號表示任意非換行符的字符,星號表示匹配它前面的字符0次或者任意多次。所以“.*”表示匹配一串任意長度的字符串任意次。
- 這個時候必須在“.*”的前后加其他的符號來限定范圍,否則得到的結(jié)果就是原來的整個字符串。
- 如果在“.*”的后面加一個問號,變成 “.*?”,那么可以得到什么樣的結(jié)果呢?問號表示匹配它前面的符號0次或者1次。于是 “.*?” 的意思就是匹配一個能滿足要求的最短字符串。
使用“(.*)”得到的是只有一個元素的列表,里面是一個很長的字符串。
使用“(.*?)”得到的結(jié)果是包含3個元素的列表,每個元素直接對應(yīng)原來文本中的每個密碼。
總結(jié):
①“.*”:貪婪模式,獲取最長的滿足條件的字符串。②“.*?”:非貪婪模式,獲取最短的能滿足條件的字符串。
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()的時候,程序內(nèi)部調(diào)用的是_compile()方法;當使用re.finall()的時候,在模塊內(nèi)部自動先調(diào)用了_compile()方法,再調(diào)用findall()方法。re.findall()自帶re.compile()的功能,所以沒有必要使用re.compile()。
4.2 先抓大再抓小
一些無效內(nèi)容和有效內(nèi)容可能具有相同的規(guī)則。這種情況下很容易把有效內(nèi)容和無效內(nèi)容混在一起,如下面這段文字:
有效用戶:姓名: 張三姓名: 李四姓名: 王五無效用戶:姓名: 不知名的小蝦米姓名: 隱身的張大俠
有效用戶和無效用戶的名字前面都以“姓名: ”開頭,如果使用“姓名: (.*?)\n”來進行匹配,就會把有效信息和無效信息混在一起,難以區(qū)分:
要解決這個問題,就需要使用先抓大再抓小的技巧。先把有效用戶這個整體匹配出來,再從有效用戶里面匹配出人名:
4.3 括號內(nèi)和括號外
在上面的例子中,括號和“.*?”都是一起使用的,因此可能會有讀者認為括號內(nèi)只能有這3種字符,不能有其他普通的字符。但實際上,括號內(nèi)也可以有其他字符,對匹配結(jié)果的影響結(jié)果如下:
其實不難理解,只需要記?。?quot;按照匹配規(guī)則查找,括號內(nèi)的被提取" 就可以了!
總結(jié)
到此這篇關(guān)于Pyhton爬蟲知識之正則表達式的文章就介紹到這了,更多相關(guān)Pyhton爬蟲正則表達式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實現(xiàn)去除圖片中指定顏色的像素功能示例
這篇文章主要介紹了Python實現(xiàn)去除圖片中指定顏色的像素功能,結(jié)合具體實例形式分析了Python基于pil與cv2模塊的圖形載入、運算、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下2019-04-04快速解決Django關(guān)閉Debug模式無法加載media圖片與static靜態(tài)文件
這篇文章主要介紹了快速解決Django關(guān)閉Debug模式無法加載media圖片與static靜態(tài)文件的操作方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04Python使用multiprocessing如何實現(xiàn)多進程
這篇文章主要介紹了Python使用multiprocessing如何實現(xiàn)多進程問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02Python操作MongoDB的教程詳解(插,查,改,排,刪)
MongoDB是一個基于分布式文件存儲的數(shù)據(jù)庫。是一個介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫當中功能最豐富,最像關(guān)系數(shù)據(jù)庫的。本文將詳細和大家聊聊Python操作MongoDB的方法,需要的可以參考一下2022-09-09Python+OpenCV實戰(zhàn)之拖拽虛擬方塊的實現(xiàn)
這篇文章主要介紹了如何利用Python+OpenCV實現(xiàn)拖拽虛擬方塊的效果,即根據(jù)手指坐標位置和矩形的坐標位置,判斷手指點是否在矩形上,如果在則矩形跟隨手指移動,感興趣的可以了解一下2022-08-08Scrapy框架實現(xiàn)的登錄網(wǎng)站操作示例
這篇文章主要介紹了Scrapy框架實現(xiàn)的登錄網(wǎng)站操作,結(jié)合實例形式分析了Scrapy登錄網(wǎng)站cookies方式、post請求方式登錄網(wǎng)站相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2020-02-02