python網路爬蟲之初始網路爬蟲,python緗戠粶鐖櫕鍒濆
第一次接觸到python是一個很偶然的因素,由於經常在網上看連載小說,很多小說都是上幾百的連載。因此想到能不能自己做一個工具自動下載這些小說,然後copy到電腦或者手機上,這樣在沒有網路或者網路訊號不好的時候都可以看。當時還不知道網路爬蟲的概念。工作學習中用得最多的是C編程,但是對於網路世界而言,C確實不是一個好的語音,C更多面向硬體和核心。基於想自己下載網路小說的念頭,認識到了python. 使用過後真是覺得是一門適合網路的語言,加上數不清的第三方庫可以使用。適合快速開發。當然python也在資料分析,自然語義方面也有很多優勢。這裡主要介紹在網路方面的應用。
說到網路,和我們最接近的就是網頁了。網頁主要技術是http,當然還有javascript,XML,JSON,TCP串連等一大堆前端,後端的東東,關於http的知識這裡不做多的描述,推薦看下http權威指南。
網頁都是用html語言寫的,關於HTML語言W3CSCHOOL上面有大量的介紹。而網路爬蟲就是主要針對HTML語言而言。不如下面的百度的介面,用google瀏覽器點擊F12,IE右擊滑鼠,然後選擇查看網頁原始碼。左邊是我們上網看到的百度頁面,右邊就是html原始碼。被script包含的部分就是javascript。 這個頁面主要是動態載入的頁面,顯示的內容主要是用javascript來驅動。看上去還不太直觀。下面我們看一個更簡單的
在百度一下上右擊滑鼠,然後選擇審查元素,對於的HMTL代碼就顯示出來
具體的代碼:可以看到百度一下的這幾個字在input元素裡面,代表的是這是一個輸入框
也許有人問,這和網路爬蟲以及下載小說有啥關係,別急,前面的只是個網頁的入門介紹。下面我們來看個小說的介面:下面是迅讀網的小說,左邊是小說本文,右邊是相關的網頁代碼。大家看到沒有,所有的小說本文都包含在標籤是<div>並且id=”content_1”的的元素裡面
如果我們能有工具能自動將HTML代碼對應元素內容自動下載下來。不就可以自動下載小說了。這就是網路爬蟲的功能,說白了網路爬蟲就是解析HMTL代碼並儲存下來然後進行後處理的。簡單來說就三個步驟:1 解析網頁得到資料,2 儲存資料 3 資料的後處理。下面我們就首先從第一步解析網頁得到資料開始。
訪問網頁首先要請求URL,也就是網址連結。Python提供了urllib2函數進行連結。具體如下:
import urllib2
req=urllib2.Request('http://www.baidu.com.cn')
fd=urllib2.urlopen(req)
Request裡面的第一個參數為網址的連結,裡面還可以攜帶頭資訊以及具體要傳遞給網址的資訊。這樣說比較抽象。我們用wireshark抓取一個上網的報文。在google瀏覽器中輸入www.sina.com.cn.可以看到如下資訊。這就是從電腦上發出去的請求。其中有幾個關鍵資訊:Request Method: Get. 這裡有兩種方式,Get和Post,Get主要是用於請求資料,Post可以用來提交資料。
User-Agent指的是使用者代碼,什麼意思呢。通過這些訊息,伺服器就能夠識別客戶使用的作業系統以及瀏覽器。一般伺服器可以通過來識別是否是爬蟲。這個後面講
Referer可以認為是你需要從伺服器上請求什麼網址,這裡可以看到就是sina
Accet-Encoding: 這是告訴電腦可以接受的資料壓縮方式。
是瀏覽器上輸入網址得到的抓包結果。如果我們運行程式結果會如何呢。是剛才python代碼的結果。訪問的網址是百度。從下面可以看到明顯的差別。最重要的就是User-Agent變成了Python-urllib2/2.7. 這個欄位給伺服器一個明確的提示,這是一個程式發起的網頁連結,也就是爬蟲,而不是坐在電腦前的人在訪問。由於爬蟲進行連結一樣會進行TCP等底層連結,因此為了防止大規模爬蟲同時進行網頁爬取。伺服器會根據User-Agent來判斷,如果是爬蟲,則直接拒絕。
那麼為了防止伺服器禁掉我們的申請,該如何應對呢。我們自程式中自己構造一個和真實瀏覽器一樣的User_Agent不就一樣了。
user_agent="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36"
headers={'User-Agent':user_agent}
req=urllib2.Request('http://www.baidu.com.cn','',headers)
fd=urllib2.urlopen(req)
添加了headers的描述。Request的第一個參數是網址,第二個參數是提交的資料,第三個參數是頭資訊。這裡第二個參數暫時為空白。第三個參數添加頭資訊,以字典的形式。可以看到抓包資訊如下。這裡就變成了我們和瀏覽器一樣的形式,這樣伺服器就不會認為是爬蟲了。下一步就是放心的抓取網頁資料了。
有同學可能會問,如果我不小心輸錯了網址,該怎麼辦呢。這就要用到python的異常保護機制了。代碼可以修改如下:
try:
user_agent="Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36"
headers={'User-Agent':user_agent}
req=urllib2.Request('http://www.baidu.com.cn','',headers)
fd=urllib2.urlopen(req)
print fd.read().decode('utf-8').encode('GB18030')
html=BeautifulSoup(fd.read(),"lxml")
# print html.encode('gbk')
except urllib2.URLError,e:
print e.reason
增加了保護機制,其中URLError在沒有網路連接或者伺服器不存在的情況下產生,這種情況下,異常通常會帶有reason屬性.HTTP的錯誤碼如下,具體參考HTTP權威指南
200:請求成功 處理方式:獲得響應的內容,進行處理
201:請求完成,結果是建立了新資源。新建立資源的URI可在響應的實體中得到 處理方式:爬蟲中不會遇到
202:請求被接受,但處理尚未完成 處理方式:阻塞等待
204:伺服器端已經實現了請求,但是沒有返回新的信 息。如果客戶是使用者代理程式,則無須為此更新自身的文檔視圖。 處理方式:丟棄
300:該狀態代碼不被HTTP/1.0的應用程式直接使用, 只是作為3XX類型回應的預設解釋。存在多個可用的被請求資源。 處理方式:若程式中能夠處理,則進行進一步處理,如果程式中不能處理,則丟棄
301:請求到的資源都會分配一個永久的URL,這樣就可以在將來通過該URL來訪問此資源 處理方式:重新導向到分配的URL
302:請求到的資源在一個不同的URL處臨時儲存 處理方式:重新導向到臨時的URL
304 請求的資源未更新 處理方式:丟棄
400 非法請求 處理方式:丟棄
401 未授權 處理方式:丟棄
403 禁止 處理方式:丟棄
404 沒有找到 處理方式:丟棄
5XX 回應代碼以“5”開頭的狀態代碼表示伺服器端發現自己出現錯誤,不能繼續執行請求 處理方式:丟棄
下面就是要列印出擷取到的網頁資訊了。Request返回一個擷取網頁的實體,urlopen則是實現開啟網頁fd.read()則可以列印出網頁的具體資訊
代碼裡面有這個decode和encode的訊息。這個是幹嘛用的呢。這個主要是針對網頁中的中文。Python3之前的中文輸出是一個很憂傷的事情。
print fd.read().decode('utf-8').encode('GB18030')
網頁上的資料也有自己的編碼方式,從下面的的網頁代碼看到編碼方式是utf-8.而在windows中中文的編碼方式是GBK。
因此如果不進行編碼轉換的話,網頁中的中文就會是亂碼形式:
那麼是否可以提前擷取網頁的編碼方式呢,這也是可以的。如下代碼就可以得到網頁返回的編碼方式
fd1=urllib2.urlopen(req).info()
print fd1.getparam('charset')
到此,我們已經成功的進行網頁連結,並擷取到了網頁內容。下一步就是進行網頁解析了。後面講介紹beautifulSoup,lxml,HTMLParser,scrapy,selenium等常用的爬蟲工具用法