第二章_復(fù)雜HTML解析

已經(jīng)確定目標(biāo)內(nèi)容后,應(yīng)該怎么做?

· 尋找“打印此頁”的鏈接,或者看看網(wǎng)站有沒有 HTML 樣式更友好的移動(dòng)版。
· 尋找隱藏在 JavaScript 文件里的信息。
· 所需信息是否存在于其它網(wǎng)站?網(wǎng)站上顯示的數(shù)據(jù)是不是從其它網(wǎng)站上抓取的?

再來一碗 BeautifulSoup

通過屬性查找標(biāo)簽

CSS 可以讓 HTML 元素呈現(xiàn)出差異化,使那些具有相同修飾元素呈現(xiàn)出不同的樣式。

比如一個(gè)頁面中,小說任務(wù)對(duì)話都是紅色的,任務(wù)名稱都是綠色的。源代碼里的 span 標(biāo)簽,引用了對(duì)應(yīng)的 CSS 屬性,如下所示:
"<span class="red">Heavens! what a virulent attack!</span>" replied <span class="green">the prince</span>, not in the least disconcerted by this reception.
我們可以抓出整個(gè)頁面,然后創(chuàng)建一個(gè) BeautifulSoup 對(duì)象:

from urllib.request import urlopen  
from bs4 import BeautifulSoup  
html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")  
bsObj = BeautifulSoup(html)

通過 BeautifulSoup 對(duì)象,我們可以用 find_all 函數(shù)抽取只包含在 <span class="green"></span> 標(biāo)簽里的文字,這樣就會(huì)得到一個(gè)人物名稱的 Python 列表:

name_list = bsObj.find_all('span', {'class':'green'})  
for name in name_list:      
    print(name.get_text())

代碼執(zhí)行后就會(huì)按照《戰(zhàn)爭與和平》中的人物出場順序顯示所有的人名。這是怎么實(shí)現(xiàn)的呢?

之前,我們調(diào)用 bsObj.tagName 只能獲取頁面中的第一個(gè)指定的標(biāo)簽?,F(xiàn)在,調(diào)用 bsObj.find_all(tagName, tagAttributes) 可以獲取頁面中所有指定的標(biāo)簽,不再只是第一個(gè)。

獲取人名列表之后,程序遍歷列表中所有的名字,然后打印 name.get_text(),就可以把標(biāo)簽中的內(nèi)容分開顯示了。

find() 和 find_all()

這兩個(gè)函數(shù)非常類似,BeautifulSoup 文檔里兩者的定義是這樣的:

find_all(tag, attrs, recursive, text, limit, keywords)  
find(tag, attrs, recursive, text, keywords)

標(biāo)簽參數(shù) tag 前面已經(jīng)介紹過——你可以傳一個(gè)標(biāo)簽的名稱或者多個(gè)標(biāo)簽名稱組成的列表做標(biāo)簽參數(shù)。

屬性參數(shù) attributes 是用一個(gè)Python字典封裝一個(gè)標(biāo)簽的若干屬性和對(duì)應(yīng)的屬性值。例如,下面這個(gè)函數(shù)會(huì)返回 HTML 文檔里紅色與綠色兩種顏色的 span 標(biāo)簽:

.find_all('span', {'class':{'green', 'red'}})

遞歸參數(shù) recursive 是一個(gè)布爾變量。你想抓取 HTML 文檔標(biāo)簽結(jié)構(gòu)里多少層的信息?如果設(shè)置為 True,find_all() 就會(huì)查找標(biāo)簽參數(shù)的所有子標(biāo)簽,以及子標(biāo)簽的子標(biāo)簽。如果設(shè)置為 False,find_all() 就只查找文檔的一級(jí)標(biāo)簽。(默認(rèn)值為 True)

文本參數(shù) text 有點(diǎn)不同,它是用標(biāo)簽的文本內(nèi)容去匹配,而不是用標(biāo)簽的屬性。假如我們想查找前面網(wǎng)頁中包含“the prince”內(nèi)容的標(biāo)簽數(shù)量,我們可以把之前的 find_all() 方法換成下面的代碼:

name_list = bsObj.find_all(text='the prince')  
print(len(name_list))

輸出結(jié)果為“7”。

范圍限制參數(shù) limit。find 其實(shí)等價(jià)于 find_all 的limit 等于 1 時(shí)的情形。如果你只對(duì)網(wǎng)頁中獲取的前 n 項(xiàng)結(jié)果感興趣,就可以設(shè)置它。但是前幾項(xiàng)的結(jié)果是按照網(wǎng)頁上的順序排序的。

還有一個(gè)關(guān)鍵詞參數(shù) keyword,可以讓你選擇哪些具有指定屬性的標(biāo)簽。但是,任何關(guān)鍵詞參數(shù)能夠完成的任務(wù),同樣可以用 attrs 解決。

通過標(biāo)簽參數(shù)列表傳到 .find_all() 里獲取一列標(biāo)簽,其實(shí)就是一個(gè)“或”關(guān)系的過濾器。而關(guān)鍵詞參數(shù)可以讓你增加一個(gè)“與”關(guān)系的過濾器來簡化工作。

導(dǎo)航樹

獲取屬性

在網(wǎng)絡(luò)數(shù)據(jù)采集時(shí)你經(jīng)常不需要查找標(biāo)簽的內(nèi)容,而是需要查找標(biāo)簽屬性。比如標(biāo)簽 <a> 指向的URL鏈接包含在 href 屬性中,或者 <img> 標(biāo)簽的圖片文件包含 src 屬性中,這時(shí)獲取標(biāo)簽屬性就變得非常有用了。

對(duì)于一個(gè)標(biāo)簽對(duì)象,可以用下面的代碼獲取它的全部屬性:

myTag.attrs

這行代碼返回的是一個(gè) Python 字典對(duì)象,可以獲取和操作這些屬性。比如要獲取圖片的資源位置 src,可以用下面的代碼:

myTag.attrs['src']

lambda 表達(dá)式

BeautifulSoup 允許我們把特定函數(shù)類型當(dāng)作 find_all() 函數(shù)的參數(shù)。唯一的限制條件是這些函數(shù)必須把一個(gè)標(biāo)簽作為參數(shù)且返回結(jié)果是布爾類型。 BeautifulSoup 用這個(gè)函數(shù)來評(píng)估它遇到的每個(gè)標(biāo)簽對(duì)象,最后把評(píng)估結(jié)果為“真”的標(biāo)簽保留,把其他標(biāo)簽剔除。

例如,下面的代碼就是獲取有兩個(gè)屬性的標(biāo)簽:

soup.find_all(lambda tag: len(tag.attrs) == 2)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1、獲取指定標(biāo)簽內(nèi)容 2、處理子標(biāo)簽 3、處理兄弟標(biāo)簽 4、父標(biāo)簽處理 5、正則表達(dá)式
    VB過得VB閱讀 239評(píng)論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,881評(píng)論 18 139
  • 平時(shí)很喜歡聽歌,不同的心情搭配不同的音樂,不同的氛圍伴隨不同的旋律,發(fā)現(xiàn)音樂對(duì)我來說是一個(gè)很高頻的需求,所以...
    Cuz_Loading閱讀 493評(píng)論 0 0
  • by:文琪 我遇見你,我記得你,這座城市天生就適合戀愛,你天生就適合我的靈魂。 -杜拉斯 人們大多就年少時(shí)期...
    我們USlive閱讀 5,520評(píng)論 0 1
  • 今天來對(duì)雪迪龍,聚光科技,先河環(huán)保通過經(jīng)營,管理,財(cái)務(wù),與行業(yè)增長來分 從經(jīng)營來來說雪迪龍這兩年有緩慢趨勢(shì) 總結(jié):...
    西米韜閱讀 361評(píng)論 0 0