我們可以把網(wǎng)路比作一張大網(wǎng),而爬蟲(chóng)便是在網(wǎng)上爬行的蜘蛛,可以把網(wǎng)的節(jié)點(diǎn)比作一個(gè)個(gè)網(wǎng)頁(yè),爬蟲(chóng)爬到這就相當(dāng)于訪問(wèn)了該頁(yè)面獲取了信息,節(jié)點(diǎn)間的連線比作網(wǎng)頁(yè)與網(wǎng)頁(yè)間的鏈接,這樣蜘蛛通過(guò)一個(gè)節(jié)點(diǎn)后可以順著節(jié)點(diǎn)連線繼續(xù)爬行到下一個(gè)節(jié)點(diǎn),即通過(guò)一個(gè)網(wǎng)頁(yè)繼續(xù)獲取后續(xù)的網(wǎng)頁(yè),這樣整個(gè)網(wǎng)頁(yè)的節(jié)點(diǎn)便可以被蜘蛛全部爬行,這樣網(wǎng)站的數(shù)據(jù)就可以被抓去下來(lái)了。
1.爬蟲(chóng)概述
爬蟲(chóng)就是獲取網(wǎng)頁(yè)信息并提取和保存信息的自動(dòng)化程序,接下來(lái)對(duì)個(gè)點(diǎn)進(jìn)行說(shuō)明:
獲取網(wǎng)頁(yè)
爬蟲(chóng)的第一步工作是獲取網(wǎng)頁(yè),在這里獲取網(wǎng)頁(yè)就是獲取網(wǎng)頁(yè)的源代碼,源代碼里包含網(wǎng)頁(yè)的部分有用信息,只要把源代碼獲取下來(lái),就可以從中提取我們想要的信息。
獲取網(wǎng)頁(yè)源代碼的關(guān)鍵是構(gòu)造一個(gè)Request并發(fā)送給服務(wù)器,然后接收到Response并將其解析,我們可以使用Python中提供的庫(kù)來(lái)實(shí)現(xiàn)這個(gè)操作,如Urllib、Requests等,Request和Response都可以用類庫(kù)提供數(shù)據(jù)結(jié)構(gòu)來(lái)表示,得到Response之后只需解析數(shù)據(jù)結(jié)構(gòu)中的Body部分即可,也就是網(wǎng)頁(yè)源代碼。
提取信息
在完成第一步獲取網(wǎng)頁(yè)源代碼后,接下來(lái)就是分析網(wǎng)頁(yè)源代碼,從中提取我們想要的數(shù)據(jù),主要有兩種方法來(lái)提取信息:
第一種方法,通過(guò)正則表達(dá)式提取,這是一個(gè)萬(wàn)能的方法,但在構(gòu)造正則表達(dá)式的時(shí)候比較復(fù)雜且容易出錯(cuò)。
第二種方法,網(wǎng)頁(yè)的結(jié)構(gòu)是有一定規(guī)則的,所以有一些根據(jù)網(wǎng)頁(yè)節(jié)點(diǎn)屬性、CSS選擇器或XPath來(lái)提取網(wǎng)頁(yè)信息的庫(kù),如BeautifulSoup、PyQuery、LXML等,使用這些庫(kù)可以高效快速地從網(wǎng)頁(yè)中提取信息,如節(jié)點(diǎn)的屬性、文本值等內(nèi)容。
提取信息是爬蟲(chóng)非常重要的部分,可以使雜亂的數(shù)據(jù)變得清晰條理,以便于我們后續(xù)對(duì)數(shù)據(jù)進(jìn)行處理和分析。
保存數(shù)據(jù)
提取數(shù)據(jù)后我們一般會(huì)將提取到的數(shù)據(jù)保存在某處以便后續(xù)處理數(shù)據(jù)使用。保存形式有很多種,可以簡(jiǎn)單保存為T(mén)XT文本或Json文本,也可以保存到數(shù)據(jù)庫(kù),如MySQL、MongoDB等,也可保存至遠(yuǎn)程服務(wù)器,如借助Sftp進(jìn)行操作等。
自動(dòng)化程序
即爬蟲(chóng)可以代替人來(lái)完成上述工作,我們可以手工提取這些信息,但當(dāng)量特別大或者想快速獲取大量數(shù)據(jù)的話就需要借助程序了。爬蟲(chóng)就是代替我們來(lái)完成這份爬取數(shù)據(jù)的工作的自動(dòng)化程序,它可以在抓去過(guò)程中進(jìn)行各種異常處理、錯(cuò)誤重試等操作,確保爬取持續(xù)有效地運(yùn)行。
2.能抓取怎樣的數(shù)據(jù)
HTML源代碼,在網(wǎng)頁(yè)中可以看到各種各樣的信息,最常見(jiàn)的便是常規(guī)網(wǎng)頁(yè),其都對(duì)應(yīng)著HTML代碼。
Json字符串,有些網(wǎng)頁(yè)返回的不是HTML代碼,而是返回一個(gè)Json字符串,API接口大多采用這樣的方式,方便數(shù)據(jù)的傳輸和解析,這種數(shù)據(jù)同樣可以抓取,而且數(shù)據(jù)提取更加方便。
二進(jìn)制數(shù)據(jù),網(wǎng)頁(yè)中還有各種二進(jìn)制數(shù)據(jù),如圖片、視頻、音頻等,我們可以利用爬蟲(chóng)將它們的二進(jìn)制數(shù)據(jù)抓取下來(lái),然后保存對(duì)應(yīng)的文件名。
各種擴(kuò)展名的文件,如CSS、JavaScript、配置文件等,這些也是普通的文件,只要在瀏覽器里能訪問(wèn)到就可以將其抓取下來(lái)。
以上內(nèi)容都對(duì)應(yīng)著各自的URL,是基于HTTP或HTTPS協(xié)議的,只要是這種數(shù)據(jù)都可以進(jìn)行抓取。
3.JavaScript渲染頁(yè)面
有時(shí)在用Urllib或Requests抓取網(wǎng)頁(yè)時(shí),得到的源代碼和瀏覽器中看到的是不一樣的。
這是一個(gè)常見(jiàn)問(wèn)題,現(xiàn)在網(wǎng)頁(yè)越來(lái)越多采用Ajax、前端模塊化工具來(lái)構(gòu)建頁(yè)面,整個(gè)網(wǎng)頁(yè)可能都是JavaScript渲染出來(lái)的,意思就是說(shuō)原始的HTML代碼就是一個(gè)空殼。
對(duì)于一個(gè)使用JavaScript渲染出來(lái)的網(wǎng)頁(yè),在使用Urllib或Requests等庫(kù)來(lái)請(qǐng)求頁(yè)面時(shí),得到的只是HTML代碼,它不會(huì)幫助我們繼續(xù)加載JavaScript文件,這樣也就看不到瀏覽器中的內(nèi)容了。對(duì)于這種情況,我們可以分析其后臺(tái)Ajax接口,也可使用Selenium、Splash這樣的庫(kù)來(lái)實(shí)現(xiàn)JavaScript渲染,這樣我們便可以爬取JavaScript渲染頁(yè)面的內(nèi)容。