




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Python
網(wǎng)絡(luò)數(shù)據(jù)采集
目錄
第一部分創(chuàng)建爬蟲
第1章初見(jiàn)網(wǎng)絡(luò)爬蟲
1.1網(wǎng)絡(luò)連接
1.2BeautifulSoup簡(jiǎn)介
1.2.1安裝BeautifulSoup
122運(yùn)行BeautifulSoup
123可靠的網(wǎng)絡(luò)連接
第2章復(fù)雜HTML解析
2.1不是一直都要用錘子
2.2再端——碗BeautifulSoup
2.2.1BeautifulSoup的find口和findAll。
222其他BeautifulSoup對(duì)象
2.2.3導(dǎo)航樹
2.3正則表達(dá)式
2.4正貝U表達(dá)式和BeautifulSoup
2.5獲取屬性
2.6Lambda表達(dá)式
2.7超越BeautifulSoup
第3章開(kāi)始采集
3.1遍歷單個(gè)域名
3.2采集整個(gè)網(wǎng)站
收集整個(gè)網(wǎng)站數(shù)據(jù)
3.3通過(guò)互聯(lián)網(wǎng)采集
3.4用ScraDV采集
第4章使用API
4.1API概述
4.2API通用規(guī)則
421方法
4.2.2驗(yàn)證
4.3服務(wù)器響應(yīng)
API調(diào)用
4.4EchoNest
幾個(gè)示例
4.5TwitterAPI
4.5.1開(kāi)始
4.5.2幾個(gè)示例
4.6GoogleAPI
4.6.1開(kāi)始
4.6.2幾個(gè)示例
4.7解析ISON數(shù)據(jù)
4.8M到主題
4.9再說(shuō)一點(diǎn)API
第5章存儲(chǔ)數(shù)據(jù)
5.1媒體文件
5.2把數(shù)據(jù)存儲(chǔ)到CSV
5.3MySQL
5.3.1安裝MySOL
5.3.2基本命令
5.3.3與Python整合
534數(shù)據(jù)庫(kù)技術(shù)與最佳實(shí)踐
5.3.5MySQL里的“六度空間游戲),
5.4Email
第6章讀取文檔
6.1文檔編碼
6.2純文本
文本編碼和全球互聯(lián)網(wǎng)
6.3CSV
讀取CSV文件
6.4PDF
6.5微軟Word和.docx
第二部分高級(jí)數(shù)據(jù)采集
第7章數(shù)據(jù)清洗
7.1編寫代碼清洗數(shù)據(jù)
數(shù)據(jù)標(biāo)準(zhǔn)化
7.2數(shù)據(jù)存儲(chǔ)后再清洗
OpenRefine
第8章自然語(yǔ)言處理
8.1概括數(shù)據(jù)
8.2馬爾可夫模型
維基白科六度分割:終結(jié)篇
8.3自然語(yǔ)言工具包
8.3.1安裝與設(shè)置
8.3.2用NLTK做統(tǒng)計(jì)分析
8.3.3用NLTK做詞性分析
8.4其他資源
第9章穿越網(wǎng)頁(yè)表單與登錄窗口進(jìn)行采集
9.1PythonRequests庫(kù)
9.2提交一個(gè)基本表單
9.3單選按鈕、復(fù)選框和其他輸入
9.4提交文件和圖像
9.5處理登錄和cookie
HTTP基本接入認(rèn)證
9.6其他表單問(wèn)題
第10章采集JavaScript
10.1lavaScript簡(jiǎn)介
常用lavaScriDt庫(kù)
10.2Ajax和動(dòng)態(tài)HTML
在Python中用Selenium執(zhí)行l(wèi)avaScript
10.3處理重定向
第11章圖像識(shí)別與文字處理
11.1OCR庫(kù)概述
11.1.1Pillow
11.1.2Tesseract
11.1.3NumPy
11.2處理格式規(guī)范的文字
從網(wǎng)站圖片中抓取文字
1L3讀取驗(yàn)證碼與訓(xùn)I練Tesseract
訓(xùn)練Tesseract
11.4獲取驗(yàn)證碼提交答案
第12章避開(kāi)采集陷阱
12.1道德規(guī)范
12.2讓網(wǎng)絡(luò)機(jī)器人看起來(lái)像人類用戶
1221修改請(qǐng)求頭
12.2.2處壬里cookie
12.2.3時(shí)間就是一切
12.3常見(jiàn)表單安全措施
12.3.1隱含輸入字段值
12.3.2避免蜜罐
12.4問(wèn)題檢查表
第13章用爬蟲測(cè)試網(wǎng)站
13.1測(cè)試簡(jiǎn)介
什么是單元測(cè)試
13.2Pvthon單元測(cè)試
測(cè)試維基百科
13.3Selenium單元測(cè)試
與網(wǎng)站進(jìn)行交互
134Python單元測(cè)試與Selenium單元測(cè)試的選擇
第14章遠(yuǎn)程采集
14.1為什么要用遠(yuǎn)程服務(wù)器
14.1.1避免IP地址被封殺
14.1.2移植性與擴(kuò)展性
14.2Tor代理服務(wù)器
PySocks
14.3遠(yuǎn)程主機(jī)
14.3.1從網(wǎng)站主機(jī)運(yùn)行
1432從云主機(jī)運(yùn)行
14.4其他資源
14.5勇往直前
附錄APython簡(jiǎn)介
安裝與"Hello.World!”
附錄B互聯(lián)網(wǎng)簡(jiǎn)介
附錄C網(wǎng)絡(luò)數(shù)據(jù)采集的法律與道德約束
C.1商標(biāo)、版權(quán)、專利
版權(quán)法
C.2侵犯動(dòng)產(chǎn)
C.3計(jì)算機(jī)欺詐與濫用法
C.4robots.txt和服務(wù)協(xié)議
C.5三個(gè)網(wǎng)絡(luò)爬蟲
C.5.1eBay起訴Bidder'sEdge與侵犯動(dòng)產(chǎn)
C.5.2美國(guó)政府起訴Auernheimer與《計(jì)算機(jī)欺詐與濫用法》
C.5.3Field起訴Google:版權(quán)和robots.txt
第一部分創(chuàng)建爬蟲
這部分內(nèi)容重點(diǎn)介紹網(wǎng)絡(luò)數(shù)據(jù)采集的基本原理:如何用Python從網(wǎng)絡(luò)服務(wù)器請(qǐng)求信息,
如何對(duì)服務(wù)器的響應(yīng)進(jìn)行基本處理,以及如何以自動(dòng)化手段與網(wǎng)站進(jìn)行交互。最終,你將
輕松游弋于網(wǎng)絡(luò)空間,創(chuàng)建出具有域名切換、信息收集以及信息存儲(chǔ)功能的爬蟲。
說(shuō)實(shí)話,如果你想以較少的預(yù)先投入獲取較高的回報(bào),網(wǎng)絡(luò)數(shù)據(jù)采集肯定是一個(gè)值得踏入
的神奇領(lǐng)域。大體上,你遇到的90%的網(wǎng)絡(luò)數(shù)據(jù)采集項(xiàng)目使用的都是接下來(lái)的六章里介
紹的技術(shù)。這部分內(nèi)容涵蓋了一般人(也包括技術(shù)達(dá)人)在思考“網(wǎng)絡(luò)爬蟲”時(shí)通常的想法
?通過(guò)網(wǎng)站域名獲取HTML數(shù)據(jù)
?根據(jù)目標(biāo)信息解析數(shù)據(jù)
?存儲(chǔ)目標(biāo)信息
?如果有必要,移動(dòng)到另一個(gè)網(wǎng)頁(yè)重復(fù)這個(gè)過(guò)程
這將為你學(xué)習(xí)本書第二部分中更復(fù)雜的項(xiàng)目奠定堅(jiān)實(shí)的基礎(chǔ)。不要天真地認(rèn)為這部分內(nèi)容
沒(méi)有第二部分里的一些比較高級(jí)的項(xiàng)目重要。其實(shí),當(dāng)你寫自己的網(wǎng)絡(luò)爬蟲時(shí),幾乎每天
都要用到第一部分的所有內(nèi)容。
第1章初見(jiàn)網(wǎng)絡(luò)爬蟲
一旦你開(kāi)始采集網(wǎng)絡(luò)數(shù)據(jù),就會(huì)感受到瀏覽器為我們做的所有細(xì)節(jié)。網(wǎng)絡(luò)上如果沒(méi)有
HTML文本格式層、CSS樣式層、JavaScript執(zhí)行層和圖像渲染層,乍看起來(lái)會(huì)有點(diǎn)兒嚇
人,但是在這一章和下一章,我們將介紹如何不通過(guò)瀏覽器的幫助來(lái)格式化和理解數(shù)據(jù)。
本章將首先向網(wǎng)絡(luò)服務(wù)器發(fā)送GET請(qǐng)求以獲取具體網(wǎng)頁(yè),再?gòu)木W(wǎng)頁(yè)中讀取HTML內(nèi)容,
最后做一些簡(jiǎn)單的信息提取,將我們要尋找的內(nèi)容分離出來(lái)。
1.1網(wǎng)絡(luò)連接
如果你沒(méi)在網(wǎng)絡(luò)或網(wǎng)絡(luò)安全上花過(guò)太多時(shí)間,那么互聯(lián)網(wǎng)的原理可能看起來(lái)有點(diǎn)兒神秘。
準(zhǔn)確地說(shuō),每當(dāng)打開(kāi)瀏覽器連接http:〃的時(shí)候,我們不會(huì)思考網(wǎng)絡(luò)正在做什
么,而且如今也不必思考。實(shí)際上,我認(rèn)為很神奇的是,計(jì)算機(jī)接口已經(jīng)如此先進(jìn),讓大
多數(shù)人上網(wǎng)的時(shí)候完全不思考網(wǎng)絡(luò)是如何工作的。
但是,網(wǎng)絡(luò)數(shù)據(jù)采集需要拋開(kāi)一些接口的遮擋,不僅是在瀏覽器層(它如何解釋所有的
HTML、CSS和JavaScript),有時(shí)也包括網(wǎng)絡(luò)連接層。
我們通過(guò)下面的例子讓你對(duì)瀏覽器獲取信息的過(guò)程有一個(gè)基本的認(rèn)識(shí)。Alice有一臺(tái)網(wǎng)絡(luò)
服務(wù)器。Bob有一個(gè)臺(tái)式機(jī)正準(zhǔn)備連接Alice的服務(wù)器。當(dāng)一臺(tái)機(jī)器想與另一臺(tái)機(jī)器對(duì)話
時(shí),下面的某個(gè)行為將會(huì)發(fā)生。
1.Bob的電腦發(fā)送一串1和0比特值,表示電路上的高低電壓。這些比特構(gòu)成了一種信息,
包括請(qǐng)求頭和消息體。請(qǐng)求頭包含當(dāng)前Bob的本地路由器MAC地址和Alice的IP地址。
消息體包含Bob對(duì)Alice服務(wù)器應(yīng)用的請(qǐng)求。
2.Bob的本地路由器收到所有1和0比特值,把它們理解成一個(gè)數(shù)據(jù)包(packet),從
Bob自己的MAC地址"寄到"Alice的IP地址。他的路由器把數(shù)據(jù)包"蓋上"自己的IP地址作
為“發(fā)件”地址,然后通過(guò)互聯(lián)網(wǎng)發(fā)出去。
3.Bob的數(shù)據(jù)包游歷了一些中介服務(wù)器,沿著正確的物理/電路路徑前進(jìn),到了Alice的
服務(wù)器。
4.Alice的服務(wù)器在她的IP地址收到了數(shù)據(jù)包。
5.Alice的服務(wù)器讀取數(shù)據(jù)包請(qǐng)求頭里的目標(biāo)端口(通常是網(wǎng)絡(luò)應(yīng)用的80端口,可以理解
成數(shù)據(jù)包的“房間號(hào)",IP地址就是“街道地址”),然后把它傳遞到對(duì)應(yīng)的應(yīng)用一一網(wǎng)絡(luò)服
務(wù)器應(yīng)用上。
6.網(wǎng)絡(luò)服務(wù)器應(yīng)用從服務(wù)器處理器收到一串?dāng)?shù)據(jù),數(shù)據(jù)是這樣的:
?這是一個(gè)GET請(qǐng)求
?請(qǐng)求文件index.html
7.網(wǎng)絡(luò)服務(wù)器應(yīng)用找到對(duì)應(yīng)的HTML文件,把它打包成一個(gè)新的數(shù)據(jù)包發(fā)送給Bob,然后
通過(guò)它的本地路由器發(fā)出去,用同樣的過(guò)程回傳到Bob的機(jī)器上。
瞧!我們就這樣實(shí)現(xiàn)了互聯(lián)網(wǎng)。
那么,在這場(chǎng)數(shù)據(jù)交換中,網(wǎng)絡(luò)瀏覽器從哪里開(kāi)始參與的?完全沒(méi)有參與。其實(shí),在互聯(lián)
網(wǎng)的歷史中,瀏覽器是一個(gè)比較年輕的發(fā)明,始于1990年的Nexus瀏覽器。
的確,網(wǎng)絡(luò)瀏覽器是一個(gè)非常有用的應(yīng)用,它創(chuàng)建信息的數(shù)據(jù)包,發(fā)送它們,然后把你獲
取的數(shù)據(jù)解釋成漂亮的圖像、聲音、視頻和文字。但是,網(wǎng)絡(luò)瀏覽器就是代碼,而代碼是
可以分解的,可以分解成許多基本組件,可重寫、重用,以及做成我們想要的任何東西。
網(wǎng)絡(luò)瀏覽器可以讓服務(wù)器發(fā)送一些數(shù)據(jù),到那些對(duì)接無(wú)線(或有線)網(wǎng)絡(luò)接口的應(yīng)用上,
但是許多語(yǔ)言也都有實(shí)現(xiàn)這些功能的庫(kù)文件。
讓我們看看Python是如何實(shí)現(xiàn)的:
fromurllib.request
html
你可以把這段代碼保存為scrapetestpy,然后在終端里運(yùn)行如下命令:
scrapetest.py
注意,如果你的設(shè)備上安裝了Python2.x,可能需要直接指明版本才能運(yùn)行Python3.x代
碼:
fpython
這將會(huì)輸出http:〃/pages/page/.html這個(gè)網(wǎng)頁(yè)的全部HTML代碼。
更準(zhǔn)確地說(shuō),這會(huì)輸出在域名為http:〃的服務(wù)器上<網(wǎng)絡(luò)應(yīng)用根地
址>/pages文件夾里的HTML文件pagel.html的源代碼。
有什么區(qū)別?現(xiàn)在大多數(shù)網(wǎng)頁(yè)需要加載許多相關(guān)的資源文件??赡苁菆D像文件、
JavaScript文件、CSS文件,或你需要連接的其他各種網(wǎng)頁(yè)內(nèi)容。當(dāng)網(wǎng)絡(luò)瀏覽器遇到一個(gè)
標(biāo)簽時(shí),比如src="cb(t&Kittei^.jpg">,會(huì)向服務(wù)器發(fā)起另一個(gè)請(qǐng)求,以獲取
cuteKittemjpg文件中的數(shù)據(jù)為用戶充分渲染網(wǎng)頁(yè)。但是,我們的Python程序沒(méi)有返回并
向服務(wù)器請(qǐng)求多個(gè)文件的邏輯,它只能讀取我們已經(jīng)請(qǐng)求的單個(gè)HTML文件。
那么它是怎樣做的呢?幸好Python語(yǔ)法接近正常英文,下面這行代碼
fromurllib.requestimporturlopen
其實(shí)已經(jīng)顯示了它的含義:它查找Python的request模塊(在urllib庫(kù)里面),只導(dǎo)入一
個(gè)ur/open函數(shù)。
urllib還是urllib2?
如果你用過(guò)Python2.x里的urllib2庫(kù),可能會(huì)發(fā)現(xiàn)urllib2與urllib有些不同。在
Python3.x里,urllib2改名為urllib,被分成一些子模塊:u"他.request、
urllib.parse和urllib.erroro盡管函數(shù)名稱大多和原來(lái)一樣,但是在用新的urllib
庫(kù)時(shí)需要注意哪些函數(shù)被移動(dòng)到子模塊里了。
urllib是Python的標(biāo)準(zhǔn)庫(kù)(就是說(shuō)你不用額外安裝就可以運(yùn)行這個(gè)例子),包含了從網(wǎng)
絡(luò)請(qǐng)求數(shù)據(jù),處理cookie,甚至改變像請(qǐng)求頭和用戶代理這些元數(shù)據(jù)的函數(shù)。我們將在
本書中廣泛使用”/他,所以建議你讀讀這個(gè)庫(kù)的Python文檔
(https:〃/3/library/urllib.html)。
ur/opc八用來(lái)打開(kāi)并讀取一個(gè)從網(wǎng)絡(luò)獲取的遠(yuǎn)程對(duì)象。因?yàn)樗且粋€(gè)非常通用的庫(kù)(它
可以輕松讀取HTML文件、圖像文件,或其他任何文件流),所以我們將在本書中頻繁
地使用它。
1.2BeautifulSoup簡(jiǎn)介
"美味的湯綠色的濃湯
在熱氣騰騰的蓋碗里裝
誰(shuí)不愿意嘗一嘗,這樣的好湯?
晚餐用的湯,美味的湯!”
BeautifulSoup庫(kù)的名字取自劉易斯?卡羅爾在《愛(ài)麗絲夢(mèng)游仙境》里的同名詩(shī)歌。在故事
中,這首詩(shī)是素甲魚1唱的。
iMockTurtle,它本身是一個(gè)雙關(guān)語(yǔ),指英國(guó)維多利亞時(shí)代的流行菜肴素甲魚湯,其實(shí)不是甲魚而是牛肉,如同
中國(guó)的豆制品素雞,名為素雞,其實(shí)與雞無(wú)關(guān)。
就像它在仙境中的說(shuō)法一樣,BeautifulSoup嘗試化平淡為神奇。它通過(guò)定位HTML標(biāo)簽
來(lái)格式化和組織復(fù)雜的網(wǎng)絡(luò)信息,用簡(jiǎn)單易用的Python對(duì)象為我們展現(xiàn)XML結(jié)構(gòu)信息。
1.2.1安裝BeautifulSoup
由于BeautifulSoup庫(kù)不是Python標(biāo)準(zhǔn)庫(kù),因此需要單獨(dú)安裝。在本書中,我們將使用最
新的BeautifulSoup4版本(也叫BS4)。BeautifulSoup4的所有安裝方法都在
/software/BeautifulSoup/bs4/doc/里面。Linux系統(tǒng)上的基本
安裝方法是:
apt-getiiastaltpgth。八-bs4
對(duì)于Mac系統(tǒng),首先用
癡d。easyj^tallPip
安裝Python的包管理器pip,然后運(yùn)行
$pipi^talIbeautifulsoup4
來(lái)安裝庫(kù)文件。
另外,注意如果你的設(shè)備同時(shí)安裝了Python2.x和Python3.x,你需要用pgthon3運(yùn)行
Python3.x:
MgSwipt.pg
當(dāng)你安裝包的時(shí)候,如果有可能安裝到了Python2.x而不是Python3.x里,就需要使用:
$sud。pythonsetup.p9install
如果用pip安裝,你還可以用pip3安裝Python3.x版本的包:
$pip3installheautiMsoup4
在Windows系統(tǒng)上安裝與在Mac和Linux上安裝差不多。從上面的下載鏈接下載最新的
BeautifulSoup4源代碼,解壓后進(jìn)入文件,然后執(zhí)行:
〉pgth。八setup.pyinstall
這樣就可以了!BeautifulSoup將被當(dāng)作設(shè)備上的一個(gè)Python庫(kù)。你可以在Python終端
里導(dǎo)入它測(cè)試一下:
$pythok\
>frombs4importBeautifulSoup
如果沒(méi)有錯(cuò)誤,說(shuō)明導(dǎo)入成功了。
另外,還有一個(gè)Windows版pip(https:〃/pypi/setuptools)的.exe格式
安裝器,裝了之后你就可以輕松安裝和管理包了:
>pipinstallbeautifulsoup4
用虛擬環(huán)境保存庫(kù)文件
如果你同時(shí)負(fù)責(zé)多個(gè)Python項(xiàng)目,或者想要輕松打包某個(gè)項(xiàng)目及其關(guān)聯(lián)的庫(kù)文件,
再或者你擔(dān)心已安裝的庫(kù)之間可能有沖突,那么你可以安裝一個(gè)Python虛擬環(huán)境來(lái)
分而治之。
當(dāng)一個(gè)Python庫(kù)不用虛擬環(huán)境安裝的時(shí)候,你實(shí)際上是全局安裝它。這通常需要有
管理員權(quán)限,或者以root身份安裝,這個(gè)庫(kù)文件對(duì)設(shè)備上的每個(gè)用戶和每個(gè)項(xiàng)目都
是存在的。好在創(chuàng)建虛擬環(huán)境非常簡(jiǎn)單:
virtuate,K\vscrapiiagEiav
這樣就創(chuàng)建了一個(gè)叫作scrapingEnv的新環(huán)境,你需要先激活它再使用:
于cdscrapingEnv/
*sourcebi^/activate
激活環(huán)境之后,你會(huì)發(fā)現(xiàn)環(huán)境名稱出現(xiàn)在命令行提示符前面,提醒你當(dāng)前處于虛擬環(huán)
境中。后面你安裝的任何庫(kù)和執(zhí)行的任何程序都是在這個(gè)環(huán)境下運(yùn)行。
在新建的scrapingEnv環(huán)境里,可以安裝并使用BeautifulSoup:
(scmpi八gEnv)電〃八*pipitostallbeautifu(soup4
(sc叼2i八gE八v)電〃八*pgtk。八
>frombs4importBeautifulSoup
>
當(dāng)不再使用虛擬環(huán)境中的庫(kù)時(shí),可以通過(guò)釋放命令來(lái)退出環(huán)境:
(scrapdeactivate
ryaircfpython
>frombs4importBeautifulSoup
Traceback(mostrecentcalllast):
FileUM1,in<module>
ImportError:Nomoduleiaa^v\ed仇4,
將項(xiàng)目關(guān)聯(lián)的所有庫(kù)單獨(dú)放在一個(gè)虛擬環(huán)境里,還可以輕松打包整個(gè)環(huán)境發(fā)送給其他
人。只要他們的Python版本和你的相同,你打包的代碼就可以直接通過(guò)虛擬環(huán)境運(yùn)
行,不需要再安裝任何庫(kù)。
盡管本書的例子都不要求你使用虛擬環(huán)境,但是請(qǐng)記住,你可以在任何時(shí)候激活并使
用它。
1.2.2運(yùn)行BeautifulSoup
BeautifulSoup庫(kù)最常用的對(duì)象恰好就是BeautifulSoup對(duì)象。讓我們把本章開(kāi)頭的例子調(diào)
整一下運(yùn)行看看:
fromurllib.requestimportuHope八
FROMbs4importBeautifulSoup
〃“ope八("kttp://www.pgtk。八scK4pM/p4ges/p4gel.ktMp')
bsObj=BeautifulSoup(ht^(.read0)
print(bsObj.hl,)
輸出結(jié)果是:
<k2>A八tinterestingTitle</hl>
和前面例子一樣,我們導(dǎo)入ur/open,然后調(diào)用hti^l.readQ獲取網(wǎng)頁(yè)的HTML內(nèi)容。
這樣就可以把HTML內(nèi)容傳到BeautifulSoup對(duì)象,轉(zhuǎn)換成下面的結(jié)構(gòu):
?htmlt<html><head>...</head><body>...</body></html>
一head-><head><title>AUsefulPage<title></head>
—titlet<title>AUsefulPage</title>
—bodyt<body><hl>AnInt...</hl><div>Loremip...</div></body>
一hl-><hl>AnInterestingTitle</hl>
一divt<div>LoremIpsumdolor...</div>
可以看出,我們從網(wǎng)頁(yè)中提取的<M>標(biāo)簽被嵌在BeautifulSoup對(duì)象bsObj結(jié)構(gòu)的第二
層(html-body-hl)。但是,當(dāng)我們從對(duì)象里提取hl標(biāo)簽的時(shí)候,可以直接調(diào)用它
bsObj.hl
其實(shí),下面的所有函數(shù)調(diào)用都可以產(chǎn)生同樣的結(jié)果:
bsObj.hti^l.body.hl
bsObj.body.kl
bsObj.kti^l.kl
希望這個(gè)例子可以向你展示BeaulMSoup庫(kù)的強(qiáng)大與簡(jiǎn)單。其實(shí),任何HTML(或
XML)文件的任意節(jié)點(diǎn)信息都可以被提取出來(lái),只要目標(biāo)信息的旁邊或附近有標(biāo)記就行。
在第3章,我們將進(jìn)一步探討一些更復(fù)雜的BeautifulSoup函數(shù),還會(huì)介紹正則表達(dá)式,
以及如何把正則表達(dá)式用于BeaiAtifbdSoup以對(duì)網(wǎng)站信息進(jìn)行提取。
1.2.3可靠的網(wǎng)絡(luò)連接
網(wǎng)絡(luò)是十分復(fù)雜的。網(wǎng)頁(yè)數(shù)據(jù)格式不友好,網(wǎng)站服務(wù)器宕機(jī),目標(biāo)數(shù)據(jù)的標(biāo)簽找不到,都
是很麻煩的事情。網(wǎng)絡(luò)數(shù)據(jù)采集最痛苦的遭遇之一,就是爬蟲運(yùn)行的時(shí)候你洗洗睡了,夢(mèng)
想著明天一早數(shù)據(jù)就都會(huì)采集好放在數(shù)據(jù)庫(kù)里,結(jié)果第二天醒來(lái),你看到的卻是一個(gè)因某
種數(shù)據(jù)格式異常導(dǎo)致運(yùn)行錯(cuò)誤的爬蟲,在前一天當(dāng)你不再盯著屏幕去睡覺(jué)之后,沒(méi)過(guò)一會(huì)
兒爬蟲就不再運(yùn)行了。那個(gè)時(shí)候,你可能想罵發(fā)明互聯(lián)網(wǎng)(以及那些奇葩的網(wǎng)絡(luò)數(shù)據(jù)格式)
的人,但是你真正應(yīng)該斥責(zé)的人是你自己,為什么一開(kāi)始不估計(jì)可能會(huì)出現(xiàn)的異常!
讓我們看看爬蟲import語(yǔ)句后面的第一行代碼,如何處理那里可能出現(xiàn)的異常:
Mtml■Hope八C""P://www.pgtk。八Serq/'ng.c。小/p〃ges/p“ge:t.kthA(")
這行代碼主要可能會(huì)發(fā)生兩種異常:
?網(wǎng)頁(yè)在服務(wù)器上不存在(或者獲取頁(yè)面的時(shí)候出現(xiàn)錯(cuò)誤)
?服務(wù)器不存在
第一種異常發(fā)生時(shí),程序會(huì)返回HTTP錯(cuò)誤。HTTP錯(cuò)誤可能是"404PageNotFound""500
InternalServerError"等。所有類似情形,八函數(shù)都會(huì)拋出"HTTPError"異常。我們
可以用下面的方式處理這種異常:
try:
=urlope^(l,http://\A/w\A/.pytho^crapiiag.coi^/pages/pagd.ktkv\lu')
exceptHTTPErrora$e:
priiat(e)
#返回空值,中斷程序,或者執(zhí)行另一個(gè)方案
eke:
#程序繼續(xù)。注意:如果你已經(jīng)在上面異常捕捉那一段代碼里返回或中斷(break),
#那么就不需要使用eke語(yǔ)句了,這段代碼也不會(huì)執(zhí)行
如果程序返回HTTP錯(cuò)誤代碼,程序就會(huì)顯示錯(cuò)誤內(nèi)容,不再執(zhí)行dsc語(yǔ)句后面的代碼。
如果服務(wù)器不存在(就是說(shuō)鏈接http:〃/打不開(kāi),或者是URL
鏈接寫錯(cuò)了),會(huì)返回一個(gè)None對(duì)象。這個(gè)對(duì)象與其他編程語(yǔ)言中的八期類
似。我們可以增加一個(gè)判斷語(yǔ)句檢測(cè)返回的向儂(是不是None:
ifisNone:
pnntC'URLisi^ot
eke:
#程序繼續(xù)
當(dāng)然,即使網(wǎng)頁(yè)已經(jīng)從服務(wù)器成功獲取,如果網(wǎng)頁(yè)上的內(nèi)容并非完全是我們期望的那樣,
仍然可能會(huì)出現(xiàn)異常。每當(dāng)你調(diào)用BeautifulSoup對(duì)象里的一個(gè)標(biāo)簽時(shí),增加一個(gè)檢查條
件保證標(biāo)簽確實(shí)存在是很聰明的做法。如果你想要調(diào)用的標(biāo)簽不存在,BeautifulSoup就
會(huì)返回None對(duì)象。不過(guò),如果再調(diào)用這個(gè)None對(duì)象下面的子標(biāo)簽,就會(huì)發(fā)生
A.ttribut&Erroir錯(cuò)誤。
下面這行代碼(nonExistentTag是虛擬的標(biāo)簽,BeautifulSoup對(duì)象里實(shí)際沒(méi)有)
的八妙s。句.八。八Exist?八七T〃g)
會(huì)返回一個(gè)None對(duì)象。處理和檢查這個(gè)對(duì)象是十分必要的。如果你不檢查,直接調(diào)用這
個(gè)None對(duì)象的子標(biāo)簽,麻煩就來(lái)了。如下所示。
print(bsObj.noi^ExistentTagsoi^eTag)
這時(shí)就會(huì)返回一個(gè)異常:
AttributeError:'N。八eTgpe'object八。attribute'soi^eTag1
那么我們?cè)趺床拍鼙苊膺@兩種情形的異常呢?最簡(jiǎn)單的方式就是對(duì)兩種情形進(jìn)行檢查:
trg:
badCoiatei^t-bs。初.八。八Existi八gTag.a八othe-Tag
exceptAttributeErrorase:
print("Tagw〃sMtfouiad")
eke:
ifbadCoiateiat==None:
priiat("Tagw〃s
else:
priiat(badColatent)
初看這些檢查與錯(cuò)誤處理的代碼會(huì)覺(jué)得有點(diǎn)兒累贅,但是,我們可以重新簡(jiǎn)單組織一下代
碼,讓它變得不那么難寫(更重要的是,不那么難讀)。例如,下面的代碼是上面爬蟲的
另一種寫法:
fromurllib.requestimport“Hope八
fromurllib.errorimportHTTPError
frombs4importBeautifulSoiAp
defg=下汨
try:
Mtm/=urlopM(url)
exceptHTTPError4se:
returnNOM
try:
bsObj=Beautifu(Soup(kt^.l.^ead())
title=bsObj.bodg.hl
exceptAttributeErrorase:
return.NOM
returntitle
title=get77Ye("kttp://www.pgtk0nscK〃/hg.C0HA/p〃ges/?age,k±M/”)
iftitle==NOM:
print(nTitlecouldnotbefoui^d")
else:
priiat(title)
在這個(gè)例子中,我們創(chuàng)建了一個(gè)getTitlc函數(shù),可以返回網(wǎng)頁(yè)的標(biāo)題,如果獲取網(wǎng)頁(yè)的
時(shí)候遇到問(wèn)題就返回一個(gè)None對(duì)象。在g&tTitle函數(shù)里面,我們像前面那樣檢查了
HTTPError,然后把兩行BeautifulSoup代碼封裝在一個(gè)try語(yǔ)句里面。這兩行中的任
何一行有問(wèn)題,AttiribiAt&Eirror都可能被拋出(如果服務(wù)器不存在,向儂/就是一■"Is-
Zone對(duì)象,hti^l.re.ad.0就會(huì)拋出Attr^uteError)(>其實(shí),我們可以在try語(yǔ)句里
面放任意多行代碼,或者放一個(gè)在任意位置都可以拋出AttnfeuteError的函數(shù)。
在寫爬蟲的時(shí)候,思考代碼的總體格局,讓代碼既可以捕捉異常又容易閱讀,這是很重要
的。如果你還希望能夠很大程度地重用代碼,那么擁有像gctSitcHTML和g&tTitle,這
樣的通用函數(shù)(具有周密的異常處理功能)會(huì)讓快速穩(wěn)定地網(wǎng)絡(luò)數(shù)據(jù)采集變得簡(jiǎn)單易行。
第2章復(fù)雜HTML解析
當(dāng)米開(kāi)朗基羅被問(wèn)及如何完成《大衛(wèi)》這樣匠心獨(dú)具的雕刻作品時(shí),他有一段著名的回答
“很簡(jiǎn)單,你只要用錘子把石頭上不像大衛(wèi)的地方敲掉就行了。”
雖然網(wǎng)絡(luò)數(shù)據(jù)采集和大理石雕刻大相徑庭,但是當(dāng)我們從復(fù)雜的網(wǎng)頁(yè)中尋覓信息時(shí).,也必
須持有類似的態(tài)度。在我們找到目標(biāo)信息之前,有很多技巧可以幫我們"敲掉”網(wǎng)頁(yè)上那些
不需要的信息。這一章我們將介紹解析復(fù)雜的HTML頁(yè)面的方法,從中抽取出我們需要
的信息。
2.1不是一直都要用錘子
面對(duì)頁(yè)面解析難題(GordianKnot)的時(shí)候,不假思索地直接寫幾行語(yǔ)句來(lái)抽取信息是非
常直接的做法。但是,像這樣魯莽放縱地使用技術(shù),只會(huì)讓程序變得難以調(diào)試或脆弱不堪,
甚至二者兼具。在開(kāi)始解析網(wǎng)頁(yè)之前,讓我們看一些在解析復(fù)雜的HTML頁(yè)面時(shí)需要避
免的問(wèn)題。
假如你已經(jīng)確定了目標(biāo)內(nèi)容,可能是采集一個(gè)名字、一組統(tǒng)計(jì)數(shù)據(jù),或者一段文字。你的
目標(biāo)內(nèi)容可能隱藏在一個(gè)HTML“爛泥堆”的第20層標(biāo)簽里,帶有許多沒(méi)用的標(biāo)簽或
HTML屬性。假如你不經(jīng)考慮地直接寫出下面這樣一行代碼來(lái)抽取內(nèi)容:
雖然也可以達(dá)到目標(biāo),但這樣看起來(lái)并不是很好。除了代碼欠缺美感之外,還有一個(gè)問(wèn)題
是,當(dāng)網(wǎng)站管理員對(duì)網(wǎng)站稍作修改之后,這行代碼就會(huì)失效,甚至可能會(huì)毀掉整個(gè)網(wǎng)絡(luò)爬
蟲。那么你應(yīng)該怎么做呢?
?尋找"打印此頁(yè)”的鏈接,或者看看網(wǎng)站有沒(méi)有HTML樣式更友好的移動(dòng)版(把
自己的請(qǐng)求頭設(shè)置成處于移動(dòng)設(shè)備的狀態(tài),然后接收網(wǎng)站移動(dòng)版,更多內(nèi)容在
第12章介紹)。
?尋找隱藏在JavaScript文件里的信息。要實(shí)現(xiàn)這一點(diǎn),你可能需要查看網(wǎng)頁(yè)加
載的JavaScript文件。我曾經(jīng)要把一個(gè)網(wǎng)站上的街道地址(以經(jīng)度和緯度呈現(xiàn)
的)整理成格式整潔的數(shù)組時(shí),查看過(guò)內(nèi)嵌谷歌地圖的JavaScript文件,里面
有每個(gè)地址的標(biāo)記點(diǎn)。
?雖然網(wǎng)頁(yè)標(biāo)題經(jīng)常會(huì)用到,但是這個(gè)信息也許可以從網(wǎng)頁(yè)的URL鏈接里獲取。
?如果你要找的信息只存在于一個(gè)網(wǎng)站上,別處沒(méi)有,那你確實(shí)是運(yùn)氣不佳。如
果不只限于這個(gè)網(wǎng)站,那么你可以找找其他數(shù)據(jù)源。有沒(méi)有其他網(wǎng)站也顯示了
同樣的數(shù)據(jù)?網(wǎng)站上顯示的數(shù)據(jù)是不是從其他網(wǎng)站上抓取后攢出來(lái)的?
尤其是在面對(duì)埋藏很深或格式不友好的數(shù)據(jù)時(shí),千萬(wàn)不要不經(jīng)思考就寫代碼,一定要三思
而后行。如果你確定自己不能另辟蹊徑,那么本章后面的內(nèi)容就是為你準(zhǔn)備的。
2.2再端一碗BeautifulSoup
在第1章里,我們快速演示了BeautifulSoup的安裝與運(yùn)行過(guò)程,同時(shí)也實(shí)現(xiàn)了每次選擇
一個(gè)對(duì)象的解析方法。在這一節(jié),我們將介紹通過(guò)屬性查找標(biāo)簽的方法,標(biāo)簽組的使用,
以及標(biāo)簽解析樹的導(dǎo)航過(guò)程。
基本上,你見(jiàn)過(guò)的每個(gè)網(wǎng)站都會(huì)有層疊樣式表(CascadingStyleSheet,CSS)?雖然你可
能會(huì)認(rèn)為,專門為了讓瀏覽器和人類可以理解網(wǎng)站內(nèi)容而設(shè)計(jì)一個(gè)展現(xiàn)樣式的層,是一件
愚蠢的事,但是CSS的發(fā)明卻是網(wǎng)絡(luò)爬蟲的福音。CSS可以讓HTML元素呈現(xiàn)出差異化,
使那些具有完全相同修飾的元素呈現(xiàn)出不同的樣式。比如,有一些標(biāo)簽看起來(lái)是這樣:
="gwen八〉
而另一些標(biāo)簽看起來(lái)是這樣:
<spaia
網(wǎng)絡(luò)爬蟲可以通過(guò)c/ass屬性的值,輕松地區(qū)分出兩種不同的標(biāo)簽。例如,它們可以用
BeautifulSoup抓取網(wǎng)頁(yè)上所有的紅色文字,而綠色文字一個(gè)都不抓。因?yàn)镃SS通過(guò)屬性
準(zhǔn)確地呈現(xiàn)網(wǎng)站的樣式,所以你大可放心,大多數(shù)新式網(wǎng)站上的c/ass和id屬性資源都
非常豐富。
下面讓我們創(chuàng)建一個(gè)網(wǎng)絡(luò)爬蟲來(lái)抓取
http:〃/pages/warandpeace.html這個(gè)網(wǎng)頁(yè)。
在這個(gè)頁(yè)面里,小說(shuō)人物的對(duì)話內(nèi)容都是紅色的,人物名稱都是綠色的。你可以看到網(wǎng)頁(yè)
源代碼里的平。八標(biāo)簽,引用了對(duì)應(yīng)的CSS屬性,如下所示:
"<spanclass="red">Heaven$!whatavirulentattack!</span>"replied.<spain.class=
“green”>theprMce</sp<m>,not認(rèn)the.leastdiscom.ce.rtedbythisreception..
我們可以抓出整個(gè)頁(yè)面,然后創(chuàng)建一個(gè)BeautifulSoup對(duì)象,和第1章里使用的程序類似:
fromurllib.requestimport“Hope八
frombs4importBeautifulSoup
htMl=urlopen("http://www.pythoiasctraping.coM/pages/waran£lpeace.htMl")
bsObjBeautifulSo(Ap(ktkv\l)
通過(guò)BeautifulSoup對(duì)象,我們可以用fin4AH函數(shù)抽取只包含在〈span
c/ass="grcen">〈/span>標(biāo)簽里的文字,這樣就會(huì)得到一個(gè)人物名稱的Python列表
(fMdAH是一個(gè)非常靈活的函數(shù),我們后面會(huì)經(jīng)常用到它):
,,,,
namgL/st=b$Obj.findAll(spaiaJ{"cSss":"g「eeW})
foriaakv\eM
代碼執(zhí)行以后就會(huì)按照《戰(zhàn)爭(zhēng)與和平》中的人物出場(chǎng)順序顯示所有的人名。這是怎么實(shí)現(xiàn)
的呢?之前,我們調(diào)用打。旬工agMwnc只能獲取頁(yè)面中的第一個(gè)指定的標(biāo)簽。現(xiàn)在,我
們調(diào)用bsObj.fin4AM(tagNa3C,tagAttributes)可以獲取頁(yè)面中所有指定的標(biāo)簽,不
再只是第一個(gè)了。
獲取人名列表之后,程序遍歷列表中所有的名字,然后打印na3&gct_tex20,就可以
把標(biāo)簽中的內(nèi)容分開(kāi)顯示了。
什么時(shí)候使用getJ:extO與什么時(shí)候應(yīng)該保留標(biāo)簽?
.gct_tcxt()會(huì)把你正在處理的HTML文檔中所有的標(biāo)簽都清除,然后返回一個(gè)只包
含文字的字符串。假如你正在處理一個(gè)包含許多超鏈接、段落和標(biāo)簽的大段源代碼,
那么.gct_tcxt。會(huì)把這些超鏈接、段落和標(biāo)簽都清除掉,只剩下一串不帶標(biāo)簽的文
字。
用BeautifulSoup對(duì)象查找你想要的信息,比直接在HTML文本里查找信息要簡(jiǎn)單得
多。通常在你準(zhǔn)備打印、存儲(chǔ)和操作數(shù)據(jù)時(shí),應(yīng)該最后才使用.g組text。。一般情
況下,你應(yīng)該盡可能地保留HTML文檔的標(biāo)簽結(jié)構(gòu)。
2.2.1BeautifulSoup的fi八W()和findAl1()
BeautifulSoup里的fMWO和可能是你最常用的兩個(gè)函數(shù)。借助它們,你可以通
過(guò)標(biāo)簽的不同屬性輕松地過(guò)濾HTML頁(yè)面,查找需要的標(biāo)簽組或單個(gè)標(biāo)簽。
這兩個(gè)函數(shù)非常相似,BeautifulSoup文檔里兩者的定義就是這樣:
fii^dAl^tagjattributes,recursive,text,keywords)
FMd(tag,attribute,recursive,text,keywords)
很可能你會(huì)發(fā)現(xiàn),自己在95%的時(shí)間里都只需要使用前兩個(gè)參數(shù):能的和attributes。
但是,我們還是應(yīng)該仔細(xì)地觀察所有的參數(shù)。
標(biāo)簽參數(shù)tag前面已經(jīng)介紹過(guò)一一你可以傳一個(gè)標(biāo)簽的名稱或多個(gè)標(biāo)簽名稱組成的
Python列表做標(biāo)簽參數(shù)。例如,下面的代碼將返回一個(gè)包含HTML文檔中所有標(biāo)題標(biāo)簽
的列表:1
?如果你想獲得文檔里的一組h<$omejevel>標(biāo)簽,可以用更簡(jiǎn)潔的方法寫代碼來(lái)完成。我們將在2.4節(jié)介紹這
類問(wèn)題的處理方法。
屬性參數(shù)attributes是用一個(gè)Python字典封裝一個(gè)標(biāo)簽的若干屬性和對(duì)應(yīng)的屬性值。例
如,下面這個(gè)函數(shù)會(huì)返回HTML文檔里紅色與綠色兩種顏色的印4八標(biāo)簽:
.fi^dAllC'spa^'j("class":{"green","red."}})
遞歸參數(shù)recursive是一個(gè)布爾變量。你想抓取HTML文檔標(biāo)簽結(jié)構(gòu)里多少層的信息、?如
果匕cursive設(shè)置為True,fMdA"就會(huì)根據(jù)你的要求去查找標(biāo)簽參數(shù)的所有子標(biāo)簽,以
及子標(biāo)簽的子標(biāo)簽。如果recursiW設(shè)置為False,finAM就只查找文檔的一級(jí)標(biāo)簽。
fMdA"默認(rèn)是支持遞歸查找的(匕cursive默認(rèn)值是True);一般情況下這個(gè)參數(shù)不需
要設(shè)置,除非你真正了解自己需要哪些信息,而且抓取速度非常重要,那時(shí)你可以設(shè)置遞
歸參數(shù)。
文本參數(shù)text有點(diǎn)不同,它是用標(biāo)簽的文本內(nèi)容去匹配,而不是用標(biāo)簽的屬性。假如我
們想查找前面網(wǎng)頁(yè)中包含“theprince”內(nèi)容的標(biāo)簽數(shù)量,我們可以把之前的findAH方法換
成下面的代碼:
b$Obj.fiiadAll(text=,,theprince")
p力八況/c八(八“meList))
輸出結(jié)果為"7"。
范圍限制參數(shù)/沁七顯然只用于行ndA"方法。fMd其實(shí)等價(jià)于fMdA"的/沁/等于1
時(shí)的情形。如果你只對(duì)網(wǎng)頁(yè)中獲取的前x項(xiàng)結(jié)果感興趣,就可以設(shè)置它。但是要注意,這
個(gè)參數(shù)設(shè)置之后,獲得的前幾項(xiàng)結(jié)果是按照網(wǎng)頁(yè)上的順序排序的,未必是你想要的那前兒
項(xiàng)。
還有一個(gè)關(guān)鍵詞參數(shù)keyword,可以讓你選擇那些具有指定屬性的標(biāo)簽。例如:
allTextbQbj.ficdAH(id="te&")
pext[O].get_te>ctQ)
關(guān)鍵詞參數(shù)的注意事項(xiàng)
雖然關(guān)鍵詞參數(shù)keyword在一些場(chǎng)景中很有用,但是,它是BeautifulSoup在技術(shù)
上做的一個(gè)冗余功能。任何用關(guān)鍵詞參數(shù)能夠完成的任務(wù),同樣可以用本章后面將介
紹的技術(shù)解決(請(qǐng)參見(jiàn)2.3節(jié)和2.6節(jié))。
例如,下面兩行代碼是完全一樣的:
b$Obj,fiiadAll(id=',texti,)
bs0tj.fi21AH(叫{"id〃:〃text'11)
另外,用keyword偶爾會(huì)出現(xiàn)問(wèn)題,尤其是在用class屬性查找標(biāo)簽的時(shí)候,因?yàn)?/p>
class是Python中受保護(hù)的關(guān)鍵字。也就是說(shuō),class是Python語(yǔ)言的保留字,在
Python程序里是不能當(dāng)作變量或參數(shù)名使用的(和前面介紹的
Beautifu(Soup.fin4A(10里的keyword無(wú)關(guān))2。假如你運(yùn)行下面的代碼,Python
就會(huì)因?yàn)槟阏`用c/ass保留字而產(chǎn)生一個(gè)語(yǔ)法錯(cuò)誤:
bs。0.fMdAH(c(ass="green")
不過(guò),你可以用BeautifulSoup提供的有點(diǎn)兒臃腫的方案,在class后面增加一個(gè)下
劃線:
bsOtj.fi~lAH(dass_="giree八")
另外,你也可以用屬性參數(shù)把dass用引號(hào)包起來(lái):
bsObj.findAHC11^{"class":,,gtreek\"})
2Python語(yǔ)言參考里提供了關(guān)鍵詞列表(https:〃docs.python,org/3/reference/lexicalanalysis.html#keywords)°
看到這里,你可能會(huì)捫心自問(wèn):“現(xiàn)在我是不是已經(jīng)知道如何用標(biāo)簽屬性獲取一組標(biāo)簽了
一一用字典把屬性傳到函數(shù)里就行了?”
回憶一下前面的內(nèi)容,通過(guò)標(biāo)簽參數(shù)tag把標(biāo)簽列表傳到出認(rèn)里獲取一列標(biāo)簽,其
實(shí)就是一個(gè)“或”關(guān)系的過(guò)濾器(即選擇所有帶標(biāo)簽1或標(biāo)簽2或標(biāo)簽3的一列標(biāo)簽)。
如果你的標(biāo)簽列表很長(zhǎng),就需要花很長(zhǎng)時(shí)間才能寫完。而關(guān)鍵詞參數(shù)keyword可以讓你
增加一個(gè)"與"關(guān)系的過(guò)濾器來(lái)簡(jiǎn)化工作。
2.2.2其他BeautifulSoup對(duì)象
看到這里,你已經(jīng)見(jiàn)過(guò)BeautifulSoup庫(kù)里的兩種對(duì)象了。
?BeautifulSoup對(duì)象
前面代碼示例中的bsObj
?標(biāo)簽Tag對(duì)象
BcautifulSoup對(duì)象通過(guò)find和findAM,或者直接調(diào)用子標(biāo)簽獲取的一列對(duì)象或單個(gè)
對(duì)象,就像:
bsObj.div.kt-
但是,這個(gè)庫(kù)還有另外兩種對(duì)象,雖然不常用,卻應(yīng)該了解一下。
?NavigableString對(duì)象
用來(lái)表示標(biāo)簽里的文字,不是標(biāo)簽(有些函數(shù)可以操作和生成NavigablcString對(duì)象,
而不是標(biāo)簽對(duì)象)。
?COMMCht對(duì)象
用來(lái)查找HTML文檔的注釋標(biāo)簽,<!--像這樣-->
這四個(gè)對(duì)象是你用BeautifulSoup庫(kù)時(shí)會(huì)遇到的所有對(duì)象(寫作本書的時(shí)候)。
2.2.3導(dǎo)航樹
findAH函數(shù)通過(guò)標(biāo)簽的名稱和屬性來(lái)查找標(biāo)簽。但是如果你需要通過(guò)標(biāo)簽在文檔中的位
置來(lái)查找標(biāo)簽,該怎么辦?這就是導(dǎo)航樹(NavigatingTrees)的作用。在第1章里,我
們看過(guò)用單一方向進(jìn)行BeautifulSoup標(biāo)簽樹的導(dǎo)航:
bsObj.tagsubTag.aMtherSubTag
現(xiàn)在我們用虛擬的在線購(gòu)物網(wǎng)站http:〃/pages/page3.html作為
要抓取的示例網(wǎng)頁(yè),演示HTML導(dǎo)航樹的縱向和橫向?qū)Ш剑ㄈ鐖D2-1所示)。
繳管TotallyNormalGifts
Hereisacollectionoftotallynormal,totallyreasonablegiftsthatyourfriendsaresuretolove!Ourcollectionishand-curak
Wehaven'tfiguredouthowtomakeonlineshoppingcartsyet.butyoucansendusacheckto:
123MainSt.
Abuja,Nigeria
Wewillthensendyourtotallyamazinggift,pronto!PleaseincludeanextraS5.00forgiRwrapping.
ItemTitleDescription
Thisvegetablebasketistheperfectgiftforyour
Vegetable
healthconscious(oroverweight)friends!Now
Basket
withsuper-colorfulbellpeppers!
Hand-paintedbytrainedmonkeys,these
Russian
exquisitedollsarepriceless!AndbyMpriceless,M
Nesting
wemean"extremelyexpensive"!8entiredolls
Dolls
perset!Octuplethepresents!
Ifsomethingseemsfishyaboutthispainting,ifs
Fish
becauseit'safish!Alsohand-paintedbytrained
Painting
monkeys!
Dead
Thisisanex-parrot!Ormaybehersonlyresting?
Parrot
圖2?1:/pages/page3.html截圖
這個(gè)HTML頁(yè)面可以映射成一棵樹(為了簡(jiǎn)潔,省略了一些標(biāo)簽),如下所示:
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 酒店?duì)I銷經(jīng)理勞動(dòng)合同范本
- 肇慶市實(shí)驗(yàn)中學(xué)高三生物三四五高效課堂教學(xué)設(shè)計(jì):自由組合定律專題
- 西南財(cái)經(jīng)大學(xué)天府學(xué)院《基本體操(1)》2023-2024學(xué)年第一學(xué)期期末試卷
- 四川省廣安市代市中學(xué)2025屆初三下學(xué)期教學(xué)質(zhì)量檢測(cè)試題模擬考試數(shù)學(xué)試題含解析
- 山東建筑大學(xué)《文學(xué)與大眾文化》2023-2024學(xué)年第二學(xué)期期末試卷
- 山西工程技術(shù)學(xué)院《藥物分析Ⅱ》2023-2024學(xué)年第一學(xué)期期末試卷
- 上海外國(guó)語(yǔ)大學(xué)《語(yǔ)言與社會(huì)》2023-2024學(xué)年第二學(xué)期期末試卷
- 江西工商職業(yè)技術(shù)學(xué)院《數(shù)據(jù)挖掘與人工智能》2023-2024學(xué)年第二學(xué)期期末試卷
- 上海市上海民辦張江集團(tuán)校2024-2025學(xué)年中考物理試題原創(chuàng)模擬卷(十)含解析
- 天津仁愛(ài)學(xué)院《報(bào)紙采編實(shí)戰(zhàn)訓(xùn)練》2023-2024學(xué)年第二學(xué)期期末試卷
- 中國(guó)肥胖及代謝疾病外科治療指南(2024版)解讀
- 醫(yī)院建設(shè)項(xiàng)目驗(yàn)收管理流程
- 人教版三年級(jí)下冊(cè)數(shù)學(xué)第五單元《面積》測(cè)試卷(含答案)
- 2-2生態(tài)脆弱區(qū)的綜合治理(分層練習(xí))解析版
- 2024年公務(wù)員考試公共基礎(chǔ)知識(shí)常識(shí)題庫(kù)及答案(共五套)
- 2024人工智能大模型技術(shù)財(cái)務(wù)應(yīng)用藍(lán)皮書
- 闊盤吸蟲病病因介紹
- 跨學(xué)科實(shí)踐活動(dòng)6+調(diào)查家用燃料的變遷與合理使用(教學(xué)設(shè)計(jì))九年級(jí)化學(xué)上冊(cè)同步高效課堂(人教版2024)
- 《初中語(yǔ)文非連續(xù)性文本教學(xué)實(shí)踐研究》
- 【MOOC】國(guó)情分析與商業(yè)設(shè)計(jì)-暨南大學(xué) 中國(guó)大學(xué)慕課MOOC答案
- 2025屆黑龍江省哈爾濱市師范大學(xué)附中高考英語(yǔ)二模試卷含解析
評(píng)論
0/150
提交評(píng)論