來,讓我們寫一個網(wǎng)絡(luò)爬蟲,下載頁面上所有的照片吧!

什么是網(wǎng)絡(luò)爬蟲?

網(wǎng)絡(luò)爬蟲是一種非常有意思的程序。偌大的Internet,就像是一只蜘蛛織成的大網(wǎng):一個個超級鏈接就是蛛絲,將無數(shù)頁面連接起來,而網(wǎng)絡(luò)爬蟲,則會沿著一根根蛛絲,爬遍每一個節(jié)點(diǎn)……

網(wǎng)絡(luò)爬蟲

網(wǎng)絡(luò)爬蟲能干嘛?

蜘蛛在網(wǎng)上爬來爬去,當(dāng)然不是為了健身。它會在網(wǎng)上尋覓獵物,捕捉它們,并拖回自己的窩里。

舉一個例子:某天某日的清晨,老板突然讓你將雪球網(wǎng)上所有的A股行情信息全部保存到一個Excel文件里,以便他瀏覽。你點(diǎn)開了網(wǎng)址雪球(A股行情),驚喜地發(fā)現(xiàn)有三十四頁,一條一條復(fù)制,顯然又累又笨,但是老板要看,你又不得不從,惆悵啊……

很多時候,我們會需要做這樣的工作:將某一類型的文檔全部下載保存下來,然后進(jìn)行分析。一個一個點(diǎn)擊鼠標(biāo),顯然不現(xiàn)實(shí)。那么,就做一個網(wǎng)絡(luò)爬蟲吧,自動化地把需要的東西保存下來。

網(wǎng)絡(luò)爬蟲是怎么干的?

一個簡單的網(wǎng)絡(luò)爬蟲的邏輯并不復(fù)雜,就是模仿人類瀏覽網(wǎng)頁的動作:輸入網(wǎng)址,進(jìn)入頁面,瀏覽網(wǎng)頁,點(diǎn)擊鏈接,進(jìn)入下一頁面……周而復(fù)始。

當(dāng)然,嘴上說是這樣,還得要將步驟細(xì)化一下。所以先來看看瀏覽網(wǎng)頁的時候,我們做了些什么。

當(dāng)我們?yōu)g覽網(wǎng)頁的時候,瀏覽器在做些什么?

蒂姆·伯納斯-李在發(fā)明互聯(lián)網(wǎng)的時候,為了解決頁面之間相互連接的問題,讓網(wǎng)絡(luò)瀏覽更加方便,發(fā)明了超文本標(biāo)記語言HTML。它是一個文本文檔,但是文檔中會有一些特殊的標(biāo)記——標(biāo)簽,它可以標(biāo)記出哪些位置的信息是標(biāo)題,哪些位置的信息是文本,哪些地方是圖像,哪些地方是超級鏈接。它就長這樣。

HTML

尖括號中間的就是標(biāo)簽,里面的字就是標(biāo)簽的名字,帶斜杠的表示標(biāo)記結(jié)束了。比如,<p>的意思是段落,</p>的意思就是這一段結(jié)束了。

瀏覽器可以根據(jù)標(biāo)簽,將網(wǎng)頁依照代碼的意思表現(xiàn)出來,用點(diǎn)兒術(shù)語的話,就是瀏覽器是一個HTML的解釋器。當(dāng)我們?yōu)g覽網(wǎng)頁的時候,瀏覽器會先將網(wǎng)頁的HTML文件,以及所需要的其它元素都下載到你的電腦里,然后根據(jù)HTML文件的內(nèi)容,將網(wǎng)頁展現(xiàn)在你的面前。

所以網(wǎng)絡(luò)爬蟲也需要干這件事情:下載HTML文件,然后分析它,根據(jù)分析的結(jié)果將需要的文本或者圖像什么的下載下來,找到超級鏈接,繼續(xù)……

讓我們寫一個網(wǎng)絡(luò)爬蟲,下載頁面上所有的照片吧!

知乎上有很多提問,下面會有很多照片,比如這個怎么用手機(jī)拍出精彩的照片?,圖片都挺好看的,我想全部下載下來,怎么辦呢?打開頁面以后,右鍵點(diǎn)擊頁面,選擇【查看源文件】,就可以看到HTML文件的內(nèi)容了。簡單分析一下,會發(fā)現(xiàn)照片其實(shí)都在這樣的標(biāo)簽下面:

img標(biāo)簽

所以,現(xiàn)在就可以制定出我們的策略了:打開頁面,分析它的HTML源文件,找出所有img標(biāo)簽,將里面的圖片都保存下來,over!

用Python實(shí)現(xiàn)你的第一個網(wǎng)絡(luò)爬蟲

Python語言語法簡單而靈活,實(shí)用的庫(別人寫好,可以直接實(shí)用的代碼)非常多,很適合寫這種小爬蟲。所以我們用Python來寫一個網(wǎng)絡(luò)爬蟲??梢渣c(diǎn)擊這里下載Python環(huán)境的安裝包,一直下一步就可以安裝好了。具體學(xué)習(xí)Python可以看這本書,或者這本書。這里我們的代碼并不復(fù)雜,需要的知識點(diǎn)不多,我會一點(diǎn)一點(diǎn)講解的。當(dāng)然你可能需要一點(diǎn)點(diǎn)程序設(shè)計(jì)的知識。

在一個文本編輯器里面輸入以下代碼:

#-*-coding:utf-8-*-

import urllib

url = "https://www.zhihu.com/question/20922273"

page = urllib.urlopen(url)

print page.read()

找一個文件夾,保存為example1.py。然后點(diǎn)擊右鍵選擇【EDIT with IDLE】。

打開以后按F5鍵。應(yīng)該會出現(xiàn)這樣的窗口。

是不是打印出了原來頁面的HTML文件的內(nèi)容?

下面來解釋一下這一段代碼的意思。

#-*-coding:utf-8-*- 的意思是這一段Python程序的編碼格式是UTF-8。理解這一點(diǎn)需要一些編碼的知識,這里暫時不用管它。一般每一個Python程序第一句話都是這個。

import urllib 的意思是導(dǎo)入urllib庫,python自帶的一個網(wǎng)絡(luò)庫,我們可以用它來實(shí)現(xiàn)訪問網(wǎng)頁,下載文件等功能。當(dāng)然還有很多功能更高級的庫,比如urllib2或者requests等,這里我們挑一個簡單的先。

url = "https://www.zhihu.com/question/20922273" 這句話的意思是定義url為字符串"https://www.zhihu.com/question/20922273" ,也就是我們要訪問的網(wǎng)頁的網(wǎng)址,可以看出,網(wǎng)址實(shí)際上是一個字符串變量。

page = urllib.urlopen(url) 這句話的意思是使用urllib庫里面的urlopen函數(shù),打開網(wǎng)址url,并把打開的這個對象命名為page(打開了一個東西,雖然我們不知道它是什么,但是先給它起個名字吧?。?。

page.read() 的意思就是讀取page這個對象的內(nèi)容。print page.read()的意思自然就是打印這個內(nèi)容了。

于是,我們就完成了第一步,打開頁面。下面,我們來寫程序分析打開的頁面。

寫程序,找出所有的圖片地址

在IDLE里面,把前面寫的代碼改一改。

#-*-coding:utf-8-*-

import urllib

from sgmllib import SGMLParser

class ZhihuParser(SGMLParser):

imgList = []

def reset(self):

? ? SGMLParser.reset(self)? #初始化

? ? self.imgList = []

? ? def start_img(self, attrs):

? ? imgUrl = [v for k, v in attrs if k=='data-original']

? ? if imgUrl:

? ? ? ? self.imgList.append(imgUrl[0])

? ? ? ? imgUrl = ""

? ? ? ? url = "https://www.zhihu.com/question/20922273"

? ? ? ? page = urllib.urlopen(url)

? ? ? ? parser = ZhihuParser()

? ? ? ? parser.feed(page.read())

? ? ? ? print parser.imgList

點(diǎn)擊F5運(yùn)行,看看結(jié)果。


下面來解釋一下代碼。

from sgmllib import SGMLParser 這一句的意思是從sgmllib文件里面導(dǎo)入SGMLParser這個包。這個包是Python自帶的一個解析HTML的庫。

class ZhihuParser(SGMLParser):是定義一個類ZhihuParser,它繼承SGMLParser這個類。我們對它進(jìn)行一些修改。

imgList = [] 聲明了一個列表,我們用它來保存所有圖片的地址。

def reset(self): 這個函數(shù)是ZhihuParser類的初始化函數(shù)。每一次生成ZhihuParser類的對象的時候都會調(diào)用這個函數(shù)。我們讓這個函數(shù)先初始化SGMLParser.reset(self),然后把列表制空self.imgList = []。

def start_img(self, attrs): 這個函數(shù)是解析img標(biāo)簽的函數(shù)。當(dāng)SGMLParser遇到一個img標(biāo)簽的時候,就會調(diào)用這個函數(shù)。比如我們要解析<a>標(biāo)簽,那就自己定義一個函數(shù)start_a,解析標(biāo)簽,就定義一個函數(shù)start_head,函數(shù)的內(nèi)容是我們需要的動作。對于這樣的結(jié)束標(biāo)簽,對應(yīng)的函數(shù)是end_something(self)。

start_something函數(shù)的參數(shù)是(self,attrs)。self自然就是類本身,attrs是SGMLParser解析出來的標(biāo)簽參數(shù),比如知乎img的代碼:

里面的src, data-rawwidth等等,都是標(biāo)簽的參數(shù),它以字典的形式傳入函數(shù)中,即一系列參數(shù)名:參數(shù)的二元對。這里我們需要提取出地址,即data-original的內(nèi)容,imgUrl = [v for k, v in attrs if k=='data-original'],意思是遍歷attrs,如果字典的名為data-original,就保存下來。

如果imgUrl保存成功,我們就把它導(dǎo)入到列表里,self.imgList.append(imgUrl[0])。然后將臨時變量imgUrl制空(這句話其實(shí)不必要)。

parser = ZhihuParser()定義了一個ZhihuParser對象,parser.feed(page.read())將頁面的內(nèi)容傳入parser,進(jìn)行解析。print parser.imgList將所有的圖片地址打印出來。

下面我們繼續(xù)修改代碼,把所有圖片保存下來。

在上面的基礎(chǔ)上加入如下代碼:

cnt=1

for?url?in?parser.imgList:

? ? f=open("%d.jpg"%cnt,'wb')

? ? img=urllib.urlopen(url)

? ? f.write(img.read())

? ? f.close()

? ? print?"%d?was?done!"%cnt

? ? cnt?+=?1

cnt = 1是定義一個計(jì)數(shù)器,記錄我們下載圖片的個數(shù)。

for url in parser.imgList:遍歷圖片地址列表。

f = open("%d.jpg"%cnt,'wb')打開一個文件。我們將下載下來的圖片寫入這個文件中。

img = urllib.urlopen(url)打開圖片地址。

f.write(img.read())將圖片寫入文件,然后關(guān)閉文件。

運(yùn)行程序,不一會就看見我們將所有的網(wǎng)頁上的圖片都下載了下來。


于是乎,我們就完成了一個最簡單的網(wǎng)絡(luò)爬蟲。

后 ? ?記

事實(shí)上,真正的通用網(wǎng)絡(luò)爬蟲是很難寫的,要考慮的因素很多。比如怎樣規(guī)避網(wǎng)站的反爬蟲機(jī)制(有的網(wǎng)站可不愿意你下載文件,占用帶寬),怎樣避免爬蟲陷阱(比如有兩個頁面有相互連接的超級鏈接,于是爬蟲就會一直在這兩個頁面間爬來爬去,不去其他頁面),怎樣大規(guī)模快速地爬(分布式爬蟲),怎樣解析JavaScript等等等等。事實(shí)上,網(wǎng)絡(luò)爬蟲是搜索引擎的核心技術(shù)之一,google,百度等搜索引擎公司每天都不停地在網(wǎng)絡(luò)上爬取頁面,解析,并排序,給我們提供搜索服務(wù)。


PS:我不太懂怎么樣在簡書打代碼。。。排版有點(diǎn)丑,請見諒。歡迎來我的Csdn看看,剛開始寫,文章不多。我以后會在上面寫一些我的學(xué)習(xí)筆記。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 前言 作為一名合格的數(shù)據(jù)分析師,其完整的技術(shù)知識體系必須貫穿數(shù)據(jù)獲取、數(shù)據(jù)存儲、數(shù)據(jù)提取、數(shù)據(jù)分析、數(shù)據(jù)挖掘、...
    whenif閱讀 18,315評論 45 523
  • Python爬蟲入門(urllib+Beautifulsoup) 本文包括:1、爬蟲簡單介紹2、爬蟲架構(gòu)三大模塊3...
    廖少少閱讀 10,085評論 0 6
  • 聲明:本文講解的實(shí)戰(zhàn)內(nèi)容,均僅用于學(xué)習(xí)交流,請勿用于任何商業(yè)用途! 一、前言 強(qiáng)烈建議:請?jiān)陔娔X的陪同下,閱讀本文...
    Bruce_Szh閱讀 13,015評論 6 28
  • 記得這樣一個電視畫面——孩子仰頭問爸爸:“什么是歷史?”爸爸微笑回答:“歷史就是過去的事情?!?自此,歷史的概念映...
    每文兒閱讀 701評論 10 9
  • 目錄 第20章:植物人嗎 第21章:能不能不看我 我低著頭看著他骨骼分明的手指,這么修長好看的手指我曾偷偷看過無數(shù)...
    九命貓兒閱讀 325評論 0 1

友情鏈接更多精彩內(nèi)容