小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

爬蟲(chóng)的解析方式三:正則表達(dá)式

 網(wǎng)摘文苑 2019-10-27

眾多語(yǔ)言都能進(jìn)行爬蟲(chóng),但基于python的爬蟲(chóng)顯得更加簡(jiǎn)潔,方便。爬蟲(chóng)也成了python語(yǔ)言中必不可少的一部分。爬蟲(chóng)的解析方式也是多種多樣。

上一篇給大家講解的是爬蟲(chóng)的解析方式二:Beautifulsoup,今天給帶給大家的是正則表達(dá)式。

爬蟲(chóng)的解析方式三:正則表達(dá)式

正則表達(dá)式

正則表達(dá)式是一個(gè)特殊的字符序列,它能幫助你方便的檢查一個(gè)字符串是否與某種模式匹配。就是 事先定義好的一些特定字符、及這些特定字符的組合,組成一個(gè)“規(guī)則字符”,這個(gè)“規(guī)則字符” 來(lái)表達(dá)對(duì)字符的一種過(guò)濾邏輯。

正則并不是python獨(dú)有的,其他語(yǔ)言也都有正則。

python中的正則,封裝了re模塊

Python中常用的正則表達(dá)式處理函數(shù)

re.match函數(shù)

re.match 嘗試從字符串的起始位置匹配一個(gè)模式,如果不是起始位置匹配成功的話,match()就返回none。

函數(shù)語(yǔ)法:

re.match(pattern, string, flags=0)

函數(shù)參數(shù)說(shuō)明:

參數(shù) 描述

pattern 匹配的正則表達(dá)式

string 要匹配的字符串。

flags 標(biāo)志位,用于控制正則表達(dá)式的匹配方式,如:是否區(qū)分大小寫,多行匹配等等。

匹配成功re.match方法返回一個(gè)匹配的對(duì)象,否則返回None。

我們可以使用group(num) 或 groups() 匹配對(duì)象函數(shù)來(lái)獲取匹配表達(dá)式。

匹配對(duì)象方法 描述

group(num=0) 匹配的整個(gè)表達(dá)式的字符串,group() 可以一次輸入多個(gè)組號(hào),

在這種情況下它將返回一個(gè)包含那些組所對(duì)應(yīng)值的元組。

groups() 返回一個(gè)包含所有小組字符串的元組,從 1 到 所含的小組號(hào)。

import reprint(re.match('www', 'www.baidu.com').span()) # 在起始位置匹配print(re.match('com', 'www.baidu.com')) # 不在起始位置匹配

以上實(shí)例運(yùn)行輸出結(jié)果為:

(0, 3)Noneimport recontent = 'Cats are smarter than dogs'result = re.match( r'(.*) are (.*?) .*', content)print(result.group())print(result.group(1))print(result.group(2))

以上實(shí)例執(zhí)行結(jié)果如下:

Cats are smarter than dogsCatssmarterresult.group()獲取匹配的結(jié)果result.span()獲去匹配字符串的長(zhǎng)度范圍

泛匹配

其實(shí)相對(duì)來(lái)說(shuō)上面的方式并不是非常方便,其實(shí)可以將上述的正則規(guī)則進(jìn)行更改

import recontent = 'Cats are smarter than dogs'result = re.match( r'Cats.*dogs$', content)print(result)print(result.group())print(result.span())

匹配目標(biāo)

如果為了匹配字符串中具體的目標(biāo),則需要通過(guò)()括起來(lái),例子如下:

import recontent = 'Cats are 1234567 smarter than dogs'result = re.match( r'(.*)\sare\s(\d+)\s(.*?)\s.*', content) #\s匹配空格符 \d+匹配數(shù)字print(result.group())print(result.group(1))print(result.group(2))

以下為執(zhí)行結(jié)果:

Cats are smarter than dogs

Cats

1234567

貪婪匹配

先看下面代碼:

import recontent = 'Cats are 1234567 smarter than dogs'result = re.match( r'Cats.*(\d+).*dogs', content) print(result.group())print(result.group(1))

從結(jié)果中可以看出只匹配到了7,并沒(méi)有匹配到1234567,出現(xiàn)這種情況的原因是前面的.* 給匹配掉了, .*在這里會(huì)盡可能的匹配多的內(nèi)容,也就是我們所說(shuō)的貪婪匹配,

如果我們想要匹配到1234567則需要將正則表達(dá)式改為:

result = re.match( r'Cats.*?(\d+).*dogs', content)

這樣結(jié)果就可以匹配到1234567

匹配模式

很多時(shí)候匹配的內(nèi)容是存在換行的問(wèn)題的,這個(gè)時(shí)候的就需要用到匹配模式re.S來(lái)匹配換行的內(nèi)容

import recontent = '''Cats are 1234567 smarter than dogsdogs are wangwangwang'''result = re.match( r'Cats.*(\d+).*wangwangwang', content,re.S) print(result.group())print(result.group(1))

轉(zhuǎn)義

當(dāng)我們要匹配的內(nèi)容中存在特殊字符的時(shí)候,就需要用到轉(zhuǎn)移符號(hào)\,例子如下:

import recontent= 'price is $5.00'result = re.match('price is \$5\.00',content)print(result.group())

注意:

對(duì)上面的一個(gè)小結(jié):

盡量使用泛匹配,使用括號(hào)得到匹配目標(biāo),盡量使用非貪婪模式,有換行符就用re.S

強(qiáng)調(diào)re.match是從字符串的起始位置匹配一個(gè)模式

re.search方法

re.search 掃描整個(gè)字符串并返回第一個(gè)成功的匹配。

函數(shù)語(yǔ)法:

re.search(pattern, string, flags=0)

函數(shù)參數(shù)說(shuō)明:

參數(shù) 描述

pattern 匹配的正則表達(dá)式

string 要匹配的字符串。

flags 標(biāo)志位,用于控制正則表達(dá)式的匹配方式,如:是否區(qū)分大小寫,多行匹配等等。

匹配成功re.search方法返回一個(gè)匹配的對(duì)象,否則返回None。

我們可以使用group(num) 或 groups() 匹配對(duì)象函數(shù)來(lái)獲取匹配表達(dá)式。

匹配對(duì)象方法 描述

group(num=0) 匹配的整個(gè)表達(dá)式的字符串,group() 可以一次輸入多個(gè)組號(hào),

在這種情況下它將返回一個(gè)包含那些組所對(duì)應(yīng)值的元組。

groups() 返回一個(gè)包含所有小組字符串的元組,從 1 到 所含的小組號(hào)。

import recontent = 'extra things hello 123455 world_this is a Re Extra things'result = re.search('hello.*?(\d+).*?Re',content)print(result.group())print(result.group(1)

其實(shí)這個(gè)時(shí)候我們就不需要在寫^以及$,因?yàn)閟earch是掃描整個(gè)字符串

注意:所以為了匹配方便,我們會(huì)更多的用search,不用match,match必須匹配頭部,所以很多時(shí)候不是特別方

re.match與re.search的區(qū)別

re.match只匹配字符串的開(kāi)始,如果字符串開(kāi)始不符合正則表達(dá)式,則匹配失敗,函數(shù)返回None;而re.search匹配整個(gè)字符串,直到找到一個(gè)匹配。

html = '''<div id='songs-list'> <h2 class='title'>經(jīng)典老歌</h2> <p class='introduction'> 經(jīng)典老歌列表 </p> <ul id='list' class='list-group'> <li data-view='2'>一路上有你</li> <li data-view='7'> <a href='/2.mp3' singer='任賢齊'>滄海一聲笑</a> </li> <li data-view='4' class='active'> <a href='/3.mp3' singer='齊秦'>往事隨風(fēng)</a> </li> <li data-view='6'><a href='/4.mp3' singer='beyond'>光輝歲月</a></li> <li data-view='5'><a href='/5.mp3' singer='陳慧琳'>記事本</a></li> <li data-view='5'> <a href='/6.mp3' singer='鄧麗君'>但愿人長(zhǎng)久</a> </li> </ul></div>'''import re result = re.search('<li.*?active.*?singer='(.*?)'>(.*?)</a>',html,re.S)print(result.group(1), result.group(2))

觀察到<ul>節(jié)點(diǎn)里面有許多<li>節(jié)點(diǎn),其中<li>節(jié)點(diǎn)有的包含<a>節(jié)點(diǎn),有的不包含<a>節(jié)點(diǎn),<a>節(jié)點(diǎn)還有一些相應(yīng)的屬性,超鏈接和歌手名。

首先我們嘗試提取class為active的<li>節(jié)點(diǎn)內(nèi)部的超鏈接包含的歌手名和歌名。

所以我們需要提取第三個(gè)<li>節(jié)點(diǎn)下的<a>節(jié)點(diǎn)的singer屬性和文本。

所以正則表達(dá)式可以以<li>開(kāi)頭,然后接下來(lái)尋找一個(gè)標(biāo)志符active,中間的部分可以用.*?來(lái)匹配,然后接下來(lái)我們要提取singer這個(gè)屬性值,所以還需要寫入singer='(.*?)',我們需要提取的部分用小括號(hào)括起來(lái),以便于用group()方法提取出來(lái),它的兩側(cè)邊界是雙引號(hào),然后接下來(lái)還需要匹配<a>節(jié)點(diǎn)的文本,那么它的左邊界是>,右邊界是</a>,所以我們指定一下左右邊界,然后目標(biāo)內(nèi)容依然用(.*?)來(lái)匹配,所以最后的正則表達(dá)式就變成了<li.*?active.*?singer='(.*?)'>(.*?)</a>',然后我們?cè)僬{(diào)用search()方法,它便會(huì)搜索整個(gè)HTML文本,找到符合正則表達(dá)式的第一個(gè)內(nèi)容返回。

另外由于代碼有換行,所以這里第三個(gè)參數(shù)需要傳入re.S

注意:在上面兩次匹配中,search()方法的第三個(gè)參數(shù)我們都加了re.S,使得.*?可以匹配換行,所以含有換行的<li>節(jié)點(diǎn)被匹配到了,如果我們將其去掉,只會(huì)匹配到不換行的的內(nèi)容

re.findall

搜索整個(gè)字符串然后返回匹配正則表達(dá)式的所有內(nèi)容

html = '''<div id='songs-list'> <h2 class='title'>經(jīng)典老歌</h2> <p class='introduction'> 經(jīng)典老歌列表 </p> <ul id='list' class='list-group'> <li data-view='2'>一路上有你</li> <li data-view='7'> <a href='/2.mp3' singer='任賢齊'>滄海一聲笑</a> </li> <li data-view='4' class='active'> <a href='/3.mp3' singer='齊秦'>往事隨風(fēng)</a> </li> <li data-view='6'><a href='/4.mp3' singer='beyond'>光輝歲月</a></li> <li data-view='5'><a href='/5.mp3' singer='陳慧琳'>記事本</a></li> <li data-view='5'> <a href='/6.mp3' singer='鄧麗君'>但愿人長(zhǎng)久</a> </li> </ul></div>'''import reresults = re.findall('<li.*?href='/(.*?)'.*?singer='(.*?)'>(.*?)</a>', html, re.S)for result in results: print(result) print(result[0], result[1], result[2])

運(yùn)行結(jié)果:

('2.mp3', '任賢齊', '滄海一聲笑')

2.mp3 任賢齊 滄海一聲笑

('3.mp3', '齊秦', '往事隨風(fēng)')

3.mp3 齊秦 往事隨風(fēng)

('4.mp3', 'beyond', '光輝歲月')

4.mp3 beyond 光輝歲月

('5.mp3', '陳慧琳', '記事本')

5.mp3 陳慧琳 記事本

('6.mp3', '鄧麗君', '但愿人長(zhǎng)久')

6.mp3 鄧麗君 但愿人長(zhǎng)久

results = re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S)for result in results: #print(result) print(result[0], result[1], result[2])

運(yùn)行結(jié)果:

一路上有你

<a href='/2.mp3' singer='任賢齊'> 滄海一聲笑 </a>

<a href='/3.mp3' singer='齊秦'> 往事隨風(fēng) </a>

<a href='/4.mp3' singer='beyond'> 光輝歲月 </a>

<a href='/5.mp3' singer='陳慧琳'> 記事本 </a>

<a href='/6.mp3' singer='鄧麗君'> 但愿人長(zhǎng)久 </a>

\s*? 這種用法其實(shí)就是為了解決有的有換行,有的沒(méi)有換行的問(wèn)題

(<a.*?>)? 這種用法是因?yàn)閔tml中有的有a標(biāo)簽,有的沒(méi)有的,?表示匹配一個(gè)或0個(gè),正好可以用于匹配

檢索和替換

Python 的re模塊提供了re.sub用于替換字符串中的匹配項(xiàng)。

語(yǔ)法:

re.sub(pattern, repl, string, count=0)

參數(shù):

pattern : 正則中的模式字符串。

repl : 替換的字符串,也可為一個(gè)函數(shù)。

string : 要被查找替換的原始字符串。

count : 模式匹配后替換的最大次數(shù),默認(rèn) 0 表示替換所有的匹配。

import rephone = '2004-959-559 # 這是一個(gè)電話號(hào)碼'# 刪除注釋num = re.sub(r'#.*$', '', phone)print ('電話號(hào)碼 : ', num) # 移除非數(shù)字的內(nèi)容num = re.sub(r'\D', '', phone)print ('電話號(hào)碼 : ', num)

在這里我們只需要在第一個(gè)參數(shù)傳入\D來(lái)匹配所有的數(shù)字,然后第二個(gè)參數(shù)“”是替換成的字符串,要去掉的話就可以賦值為空,第三個(gè)參數(shù)phone就是原字符串。

re.compile

將正則表達(dá)式編譯成正則表達(dá)式對(duì)象,方便復(fù)用該正則表達(dá)式

import recontent= 'hello world fan' pattern =re.compile('hello.*fan',re.S) result1 = re.match(pattern,content)result2 = re.search(pattern,content)result3 = re.sub(pattern, '', content)print(result1, result2, result3)

compile()還可以傳入修飾符,例如re.S等修飾符,這樣在search()、findall()等方法中就不需要額外傳了。所以compile()方法可以說(shuō)是給正則表達(dá)式做了一層封裝,以便于我們更好地復(fù)用。

正則表達(dá)式修飾符 - 可選標(biāo)志

正則表達(dá)式可以包含一些可選標(biāo)志修飾符來(lái)控制匹配的模式。修飾符被指定為一個(gè)可選的標(biāo)志。多個(gè)標(biāo)志可以通過(guò)按位 OR(|) 它們來(lái)指定。如 re.I | re.M 被設(shè)置成 I 和 M 標(biāo)志:

修飾符 描述

re.I 使匹配對(duì)大小寫不敏感

re.L 做本地化識(shí)別(locale-aware)匹配

re.M 多行匹配,影響 ^ 和 $

re.S 使 . 匹配包括換行在內(nèi)的所有字符

re.U 根據(jù)Unicode字符集解析字符。這個(gè)標(biāo)志影響 \w, \W, \b, \B.

re.X 該標(biāo)志通過(guò)給予你更靈活的格式以便你將正則表達(dá)式寫得更易于理解。

正則表達(dá)式模式

模式字符串使用特殊的語(yǔ)法來(lái)表示一個(gè)正則表達(dá)式:

字母和數(shù)字表示他們自身。一個(gè)正則表達(dá)式模式中的字母和數(shù)字匹配同樣的字符串。

多數(shù)字母和數(shù)字前加一個(gè)反斜杠時(shí)會(huì)擁有不同的含義。

標(biāo)點(diǎn)符號(hào)只有被轉(zhuǎn)義時(shí)才匹配自身,否則它們表示特殊的含義。

反斜杠本身需要使用反斜杠轉(zhuǎn)義。

由于正則表達(dá)式通常都包含反斜杠,所以你最好使用原始字符串來(lái)表示它們。模式元素(如 r'\t',等價(jià)于 \\t )匹配相應(yīng)的特殊字符。

下表列出了正則表達(dá)式模式語(yǔ)法中的特殊元素。如果你使用模式的同時(shí)提供了可選的標(biāo)志參數(shù),某些模式元素的含義會(huì)改變。

模式 描述

^ 匹配字符串的開(kāi)頭

$ 匹配字符串的末尾。

. 匹配任意字符,除了換行符,當(dāng)re.DOTALL標(biāo)記被指定時(shí),則可以匹配包括換行符的任意字符。

[...] 用來(lái)表示一組字符,單獨(dú)列出:[amk] 匹配 'a','m'或'k'

[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。

re* 匹配0個(gè)或多個(gè)的表達(dá)式。

re+ 匹配1個(gè)或多個(gè)的表達(dá)式。

re? 匹配0個(gè)或1個(gè)由前面的正則表達(dá)式定義的片段,非貪婪方式

re{ n}

re{ n,} 精確匹配n個(gè)前面表達(dá)式。

re{ n, m} 匹配 n 到 m 次由前面的正則表達(dá)式定義的片段,貪婪方式

a| b 匹配a或b

(re) G 匹配括號(hào)內(nèi)的表達(dá)式,也表示一個(gè)組

(?imx) 正則表達(dá)式包含三種可選標(biāo)志:i, m, 或 x 。只影響括號(hào)中的區(qū)域。

(?-imx) 正則表達(dá)式關(guān)閉 i, m, 或 x 可選標(biāo)志。只影響括號(hào)中的區(qū)域。

(?: re) 類似 (...), 但是不表示一個(gè)組

(?imx: re) 在括號(hào)中使用i, m, 或 x 可選標(biāo)志

(?-imx: re) 在括號(hào)中不使用i, m, 或 x 可選標(biāo)志

(?#...) 注釋.

(?= re) 前向肯定界定符。如果所含正則表達(dá)式,以 ... 表示,在當(dāng)前位置成功匹配時(shí)成功,

否則失敗。但一旦所含表達(dá)式已經(jīng)嘗試,匹配引擎根本沒(méi)有提高;

模式的剩余部分還要嘗試界定符的右邊。

(?! re) 向前否定界定符。與肯定界定符相反;當(dāng)所含表達(dá)式不能在字符串當(dāng)前位置匹配時(shí)成功

(?> re) 匹配的獨(dú)立模式,省去回溯。

\w 匹配字母數(shù)字

\W 匹配非字母數(shù)字

\s 匹配任意空白字符,等價(jià)于 [\t\n\r\f].

\S 匹配任意非空字符

\d 匹配任意數(shù)字,等價(jià)于 [0-9].

\D 匹配任意非數(shù)字

\A 匹配字符串開(kāi)始

\Z 匹配字符串結(jié)束,如果是存在換行,只匹配到換行前的結(jié)束字符串。c

\z 匹配字符串結(jié)束

\G 匹配最后匹配完成的位置。

\b 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置。

例如, 'er\b' 可以匹配'never' 中的 'er',但不能匹配 'verb' 中的 'er'。

\B 匹配非單詞邊界。'er\B' 能匹配 'verb' 中的 'er',但不能匹配 'never' 中的 'er'。

\n, \t, 等. 匹配一個(gè)換行符。匹配一個(gè)制表符。等

\1...\9 匹配第n個(gè)分組的內(nèi)容。

\10 匹配第n個(gè)分組的內(nèi)容,如果它經(jīng)匹配。否則指的是八進(jìn)制字符碼的表達(dá)式。

正則表達(dá)式實(shí)例

字符匹配

實(shí)例 描述

python 匹配 'python'.

字符類

實(shí)例 描述

[Pp]ython 匹配 'Python' 或 'python'

rub[ye] 匹配 'ruby' 或 'rube'

[aeiou] 匹配中括號(hào)內(nèi)的任意一個(gè)字母

[0-9] 匹配任何數(shù)字。類似于 [0123456789]

[a-z] 匹配任何小寫字母

[A-Z] 匹配任何大寫字母

[a-zA-Z0-9] 匹配任何字母及數(shù)字

[^aeiou] 除了aeiou字母以外的所有字符

[^0-9] 匹配除了數(shù)字外的字符

特殊字符類

實(shí)例 描述

. 匹配除 '\n' 之外的任何單個(gè)字符。要匹配包括 '\n' 在內(nèi)的任何字符,請(qǐng)使用象 '[.\n]' 的模式。

\d 匹配一個(gè)數(shù)字字符。等價(jià)于 [0-9]。

\D 匹配一個(gè)非數(shù)字字符。等價(jià)于 [^0-9]。

\s 匹配任何空白字符,包括空格、制表符、換頁(yè)符等等。等價(jià)于 [ \f\n\r\t\v]。

\S 匹配任何非空白字符。等價(jià)于 [^ \f\n\r\t\v]。

\w 匹配包括下劃線的任何單詞字符。等價(jià)于'[A-Za-z0-9_]'。

\W 匹配任何非單詞字符。等價(jià)于 '[^A-Za-z0-9_]'。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多