當前位置:
首頁 > 最新 > Python爬蟲之urllib庫—爬蟲的第一步

Python爬蟲之urllib庫—爬蟲的第一步

第一個爬蟲代碼的實現我想應該是從urllib開始吧,博主開始學習的時候就是使用urllib庫敲了幾行代碼就實現了簡單的爬數據功能,我想大多夥伴們也都是這麼過來的。當時的感覺就是:哇,好厲害,短短几行竟然就可以搞定一個看似很複雜的任務,於是就在想這短短的幾行代碼到底是怎麼實現的呢,如何進行更高級複雜的爬取呢?帶著這個問題我也就開始了urllib庫的學習。

首先不得不提一下爬取數據的過程,弄清楚這到底是怎樣一個過程,學習urllib的時候會更方便理解。

  • 爬蟲的過程

其實,爬蟲的過程和瀏覽器瀏覽網頁的過程是一樣的。道理大家應該都明白,就是當我們在鍵盤上輸入網址點擊搜索之後,通過網路首先會經過DNS伺服器,分析網址的域名,找到了真正的伺服器。然後我們通過HTTP協議對伺服器發出GET或POST請求,若請求成功,我們就得到了我們想看到的網頁,一般都是用HTML, CSS, JS等前端技術來構建的,若請求不成功,伺服器會返回給我們請求失敗的狀態碼,常見到的503,403等。

爬蟲的過程亦是如此,通過對伺服器發出請求得到HTML網頁,然後對下載的網頁進行解析,得到我們想要的內容。當然,這是一個爬蟲過程的一個概況,其中還有很多細節的東西需要我們處理的,這些在後續會繼續與大家分享。

了解了爬蟲的基本過程後,就可以開始我們真正的爬蟲之旅了。

Python有一個內置的urllib庫,可謂是爬蟲過程非常重要的一部分了。這個內置庫的使用就可以完成向伺服器發出請求並獲得網頁的功能,所以也是學習爬蟲的第一步了。

博主用的是Python3.x,urllib庫的結構相對於Python2.x有一些出入,Python2.x中使用的urllib2和urllib庫,而Python3.x中合併成一個唯一的urllib庫。

首先,我們來看看Python3.x的urllib庫都有什麼吧。

博主用的IDE是Pycharm,編輯調試非常方便,很贊。

在控制台下輸入如下代碼:

>>importurllib

>>dir(urllib)

結果:

["__builtins__","__cached__", "__doc__", "__file__", "__loader__", "__name__", "__package__","__path__", "__spec__", "error", "parse", "request", "response"]

可以看到urllib除了以雙下劃線開頭結尾的內置屬性外,還有4個重要的屬性,分別是error,parse,request,response。

在Python的urllib庫中doc開頭是這樣簡短描述的:

Error:「Exception classesraised by urllib.」----就是由urllib舉出的exception類

Parse:「Parse (absolute andrelative) URLs.」----解析絕對和相對的URLs

Request:「An extensiblelibrary for opening URLs using a variety of protocols」

----用各種協議打開URLs的一個擴展庫

Response:「Response classesused by urllib.」----被urllib使用的response類

這4個屬性中最重要的當屬request了,它完成了爬蟲大部分的功能,我們先來看看request是怎麼用的。

request請求最簡單的操作是用urlopen方法,代碼如下

運行結果如下:

b"

發現得到的運行結果竟然是亂碼!!別著急,這是因為編碼的問題,我們只需要將請求的類文件讀取再解碼就可以了。

修改代碼如下:

運行結果:

..

...

得到的就是我們想要的html的網頁了,怎麼樣,簡單吧。

下面來介紹一下這個urlopen方法和其中應用的參數。

defurlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TI

MEOUT,*, cafile=None, capath=None,

cadefault=False, context=None):

這個urlopen的功能是打開一個URL,可以是一串字元串(如上例子中一樣),也可以是Request對象(後面會提到)。它會返回一個類文件對象,並可以針對這個對象進行各種操作(如上例中的read操作,將html全部讀出來,後面會介紹其它的幾個操作)。

data:是我們要發給伺服器請求的額外信息(比如登錄網頁需要主動填寫的用戶信息)。如果需要添加data參數,那麼是POST請求,默認無data參數時,就是GET請求;

一般來講,data參數只有在http協議下請求才有意義

data參數被規定為byte object,也就是位元組對象

data參數應該使用標準的結構,這個需要使用

data在以後實戰中會介紹如何使用

timeout:是選填的內容,定義超時時間,單位是秒,防止請求時間過長,不填就是默認的時間;

cafile:是指向單獨文件的,包含了一系列的CA認證 (很少使用,默認即可);

capath:是指向文檔目標,也是用於CA認證(很少使用,默認即可);

cafile:可以忽略

context:設置SSL加密傳輸(很少使用,默認即可);

對返回的類文件對象也可以進行其它操作:

geturl():返回URL,用於看是否有重定向。

result=response.geturl()

結果:

https://www.python.org/

info():返回元信息,例如HTTP的headers。

result=response.info()

結果:

x-xss-protection: 1; mode=block

X-Clacks-Overhead: GNU Terry Pratchett

...

Vary: Cookie

Strict-Transport-Security: max-age=63072000;includeSubDomains

getcode():返回回復的HTTP狀態碼,成功是200,失敗可能是503等,可以用來檢查代理IP的可使用性。

result=response.getcode()

結果:

200

classRequest:

def__init__(self, url, data=None, headers={},

origin_req_host=None, unverifiable=False,

method=None):

如上定義,Request是一個類,初始化中包括請求需要的各種參數:

url,data和上面urlopen中的提到的一樣。

headers是HTTP請求的報文信息,如User_Agent參數等,它可以讓爬蟲偽裝成瀏覽器而不被伺服器發現你正在使用爬蟲。

origin_reg_host, unverifiable, method等不太常用

headers很有用,有些網站設有反爬蟲機制,檢查請求若沒有headers就會報錯,因此博主為保證爬蟲的穩定性,基本每次都會將headers信息加入進去,這是反爬的簡單策略之一。

那麼如何找到你所在瀏覽器的headers呢?

可以通過進入瀏覽器F12查看到

比如,博主用的Chrome瀏覽器,按F12->network就可以查看request的headers,可以把這個瀏覽器的headers信息複製下來使用。

下面來看看Request如何使用吧,代碼如下:

結果和前面urlopen是一樣的,前面提到urlopen除了可以接受指定參數,也可以接受Request類的對象。

在需要headers的情況下,使用Request對象還是很有必要的。

" "裡面填寫自己瀏覽器的信息即可。

urllib庫的requset屬性裡面還有很多其它方法,代理、超時、認證、HTTP的POST模式下請求等內容將在下次進行分享,這次主要介紹基本功能。

下面來說說異常,urllib庫的error方法。

error屬性裡面主要包括了兩個重要的exception類,URLError類和HTTPError類。

def__init__(self, reason, filename=None):

self.args=reason,

self.reason=reason

iffilenameis not None:

self.filename=filename

URLError類是OSError的子類,繼承OSError,沒有自己的任何行為特點,但是將作為error裡面所有其它類型的基類使用。

URLError類初始化定義了reason參數,意味著當使用URLError類的對象時,可以查看錯誤的reason。

def__init__(self, url, code, msg, hdrs, fp):

self.code=code

self.msg=msg

self.hdrs=hdrs

self.fp=fp

self.filename=url

HTTPError是URLError的子類,當HTTP發生錯誤將舉出HTTPError。

HTTPError也是HTTP有效回應的實例,因為HTTP協議錯誤是有效的回應,包括狀態碼,headers和body。所以看到在HTTPError初始化的時候定義了這些有效回應的參數。

當使用HTTPError類的對象時,可以查看狀態碼,headers等。

下面我們用一個例子來看一下如何使用這兩個exception類。

importurllib.request

importurllib.error

try:

headers={"User_Agent":"Mozilla/5.0 (X11; Ubuntu;

Linux x86_64; rv:57.0) Gecko/20100101

Firefox/57.0"}

response=urllib.request.Request("http://python.org/",

headers=headers)

html=urllib.request.urlopen(response)

result=html.read().decode("utf-8")

excepturllib.error.URLErrorase:

ifhasattr(e,"reason"):

print("錯誤原因是"+str(e.reason))

excepturllib.error.HTTPErrorase:

ifhasattr(e,"code"):

print("錯誤狀態碼是"+str(e.code))

else:

print("請求成功通過。")

以上代碼使用了try..exception的結構,實現了簡單的網頁爬取,當有異常時,如URLError發生時,就會返回reason,或者HTTPError發生錯誤時就會返回code。異常的增加豐富了爬取的結構,使其更加健壯。

為什麼說更加健壯了呢?

不要小看了這些異常的錯誤,這些異常的錯誤非常好用,也非常關鍵。想想看,當你編寫一個需要不斷自動運行爬取並解析的代碼時,你是不希望程序中間被打斷而終止的。如果這些異常狀態沒有設置好,那麼就很有可能彈出錯誤而被終止,但如果設置好了完整的異常,則遇到錯誤時就會執行發生錯誤的代碼而不被打斷(比如向上面代碼一樣列印錯誤code等)。

這些打斷程序的錯誤可能是很多種,尤其當你使用代理ip池的時候,會發生很多不同錯誤,這時異常就起到作用了。

主要介紹了爬蟲的過程和urllib的使用和功能,針對爬蟲主要介紹了以下的使用方法:

後續將會分享一些request的高級功能,如自定義opener使用代理ip、超時設置、認證等,以及如何POST請求主動發送信息等,也會利用這些內容做一次實戰爬取,希望大家能更加理解。

歡迎大家一起來討論學習,後面內容敬請期待!


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python 的精彩文章:

R開發人員使用Python

TAG:Python |