我小時候曾在《科學(xué)美國人》上拜讀過一篇文章,文中對比了地球上各種不同物種的移動速率枢纠,比如熊、猩猩字逗、浣熊京郑、鳥類、魚類等——當然還有人類——計算它們每移動一公里消耗的熱量葫掉,最后禿鷲贏了些举,它的移動效率最高。作為萬物之靈的人類俭厚,排在倒數(shù)第幾位户魏。但是雜志特地測量了人類騎自行車的速率。結(jié)果把禿鷲遠遠甩在了身后挪挤,在排名上遙遙領(lǐng)先叼丑。這篇文章給我留下了深刻的印象,人類擅長發(fā)明工具扛门,工具賦予我們奇妙的能力鸠信。 蘋果以前有一條廣告:計算機是頭腦的自行車 ,我徹頭徹尾地堅信如果將來有人回顧人類歷史论寨,計算機將是人類最偉大的發(fā)明星立。
----Steve Jobs(對,就是喬布斯說的葬凳,你沒看錯4麓埂!)
那么火焰,正事來了劲装,如何高效看圖(別問我看什么圖)。
下面的內(nèi)容就是昌简,當我們有了一定的python基礎(chǔ)占业,如何寫這樣的一個宅男爬蟲(也就是實現(xiàn)打開網(wǎng)頁,尋找網(wǎng)頁中所有存有網(wǎng)頁鏈接的圖片江场,然后download圖片纺酸,并且保存在我們指定的文件夾中)。
在我的爬蟲中用到了re,os,threading,requests,time
這幾個模塊址否,其中我使用request
模塊餐蔬,替代了官方的urllib2
碎紊,為毛用requests 不用urllib2,那是因為request
的官方文檔中的這句話迷住了我:"Requests is the only Non-GMO HTTP library for Python, safe for human consumption."樊诺,嘎嘎仗考。
下面正式說思路:我們平時瀏覽網(wǎng)頁,都是在瀏覽器中輸入網(wǎng)址词爬,然后等待網(wǎng)站返回數(shù)據(jù)秃嗜,瀏覽器將網(wǎng)頁加載顯示出來。在這個過程中顿膨,主要是如下幾步:
- 瀏覽器向目標網(wǎng)站服務(wù)器發(fā)送請求锅锨,
- 目標服務(wù)器接受請求,
- 目標服務(wù)器發(fā)送響應(yīng)數(shù)據(jù)到瀏覽器恋沃。
- 瀏覽器再將獲取的數(shù)據(jù)解析必搞,形成你所看到的網(wǎng)站(要想更詳細的了解整個過程參見書: 計算機網(wǎng)絡(luò)(自頂向下法))
目標服務(wù)器的響應(yīng)數(shù)據(jù)應(yīng)該長這個樣子(有點丑,是吧囊咏,哈哈):
<head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" id="link1">Elsie</a>
<a class="sister" id="link2">Lacie</a>
<a class="sister" id="link3">Tillie</a>;and they lived at the bottom of a well.
</p>
<p class="story">...</p>
這些標題通常有特殊含義:例如<title></title>
表示文章標題恕洲,<a></a>
表示鏈接,<img href = "......" />
表示圖片鏈接梅割,我們就要獲取<img>
中href
參數(shù)的數(shù)據(jù)霜第,這里儲存著我們需要獲取的圖片鏈接地址。然后再打開這個鏈接户辞,獲取里面的圖片數(shù)據(jù)保存就大功告成了泌类。
steps (只描述實現(xiàn)思路,代碼起描述作用!5琢恰D┦摹)
靜覓爬蟲系列教程(不錯的爬蟲教程)
下面按步驟介紹實現(xiàn)思路,當你實現(xiàn)時书蚪,應(yīng)該各個功能封裝成函數(shù),或者封裝成類迅栅,并且加入異常監(jiān)測殊校,以保證代碼運行的穩(wěn)定性,并且將程序中出現(xiàn)的錯誤記入寫入log读存,方便以后查看为流。
- 調(diào)用類似下面的代碼,獲取我們所需的網(wǎng)站內(nèi)容(也就是HTML文本,CSS樣式表让簿,JavaScript):
import requests
web = requests.get('http://www.baidu.com')
print web.text```
2. 編寫正則表達式敬察,以某種特定格式匹配我們需要獲取的內(nèi)容,然后將獲取內(nèi)容保存:
import request
import re
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
有些服務(wù)器會對請求進行驗證尔当,加入headers裝作我是好人
headers = { 'User-Agent' : user_agent }
獲取目標站的Http代碼
web = requests.get(url,headers=headers)
根據(jù)目標站的Http代碼莲祸,找到我們要獲取的內(nèi)容格式特點蹂安,書寫正則,并測試
pattern = re.compile('<div.?author">.?<a.?<img.?>(.?)</a>.?<div.?'+
'content">(.?).?</div>(.?)<div class="stats.?class="number">(.?)</i>',re.S)
所有的查找匹配結(jié)果都會儲存在imgurl這個列表中
imgurl = re.findall(pattern,web.content)
3. 既然我們成功獲取了要匹配的數(shù)據(jù)(我假設(shè)是圖片鏈接)锐帜,那么就可以打開圖片鏈接進行處理
import request
import re
import os
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
有些服務(wù)器會對請求進行驗證田盈,加入headers裝作我是好人
headers = { 'User-Agent' : user_agent }
獲取目標站的Http代碼
web = requests.get(url,headers=headers)
根據(jù)目標站的Http代碼,找到我們要獲取的內(nèi)容格式特點缴阎,書寫正則允瞧,并測試
pattern = re.compile('<div.?author">.?<a.?<img.?>(.?)</a>.?<div.?'+
'content">(.?).?</div>(.?)<div class="stats.?class="number">(.?)</i>',re.S)
所有的查找匹配結(jié)果都會儲存在imgurl這個列表中
imgurl = re.findall(pattern,web.content)
創(chuàng)建要保存的文件夾
os.mkdir('/home/picture')
for item in imgurl:
imgdata = requests.get(item,headers=headers)
picorder = picorder + 1
f = open('/home/picture/'+str(picorder),'rw')
f.write()
f.flush()
f.close()
4. 當上面所有的都完成之后,你良好的運行一陣蛮拔,是否覺得下載圖片太慢述暂,那么下面我們再加入多線程
>**CPython**實現(xiàn)細節(jié):在Cpython,由于全局解釋器鎖(Global interpreter Lock GIL)建炫,每次只能有一個線程可以 執(zhí)行Python 代碼(即使某些以效率為導(dǎo)向的庫(performance-oriented libraries)可能克服這些限制)畦韭。如果你希望你的應(yīng)用更好的利用電腦的多核資源。建議你使用**multiprocessing
** 或者**concurrent.futurres.ProcessPollExector
**模塊踱卵。然而多線程仍然是適當?shù)哪K廊驼,當你使用多IO并行任務(wù)時(multiple I/O - bound tasks simultaneously)
import request
import re
import os
page = 1
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
有些服務(wù)器會對請求進行驗證,加入headers裝作我是好人
headers = { 'User-Agent' : user_agent }
獲取目標站的Http代碼
web = requests.get(url,headers=headers)
根據(jù)目標站的Http代碼惋砂,找到我們要獲取的內(nèi)容格式特點妒挎,書寫正則,并測試
pattern = re.compile('<div.?author">.?<a.?<img.?>(.?)</a>.?<div.?'+
'content">(.?).?</div>(.?)<div class="stats.?class="number">(.?)</i>',re.S)
所有的查找匹配結(jié)果都會儲存在imgurl這個列表中
imgurl = re.findall(pattern,web.content)
創(chuàng)建要保存的文件夾
os.mkdir('/home/picture')
picorder = picorder +1
當要下載內(nèi)容不空時西饵,開啟4個下載線程
while items:
if threading.activeCount()<5:
a = threading.Thread(target=downfunc,args=(items.pop(),picoder))
a.start()
定義一個下載函數(shù)
def downfunc(url,order)
imgdata = requests.get(url,headers=headers)
f = open('/home/picture/'+str(order),'rw')
f.write()
f.flush()
f.close()
整體代碼思路就向上面類似酝掩,不過自己實現(xiàn)要學(xué)習(xí)**```request,re,threading,os```**這幾個庫,關(guān)于匹配還可以引入**```beautifulsoup```** 或者**```xpath```**更方便快捷的解析```HTML```文本眷柔。革命尚未成功期虾,同志仍需努力!Q敝觥O獍!>掀馈茂蚓!