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