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


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


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


  • 爬蟲的過程python

  

其實,爬蟲的過程和瀏覽器瀏覽網頁的過程是同樣的。道理你們應該都明白,就是當咱們在鍵盤上輸入網址點擊搜索以後,經過網絡首先會通過DNS服務器,分析網址的域名,找到了真正的服務器。而後咱們經過HTTP協議對服務器發出GETPOST請求,若請求成功,咱們就獲得了咱們想看到的網頁,通常都是用HTML, CSS, JS等前端技術來構建的,若請求不成功,服務器會返回給咱們請求失敗的狀態碼,常見到的503403等。瀏覽器

 

爬蟲的過程亦是如此,經過對服務器發出請求獲得HTML網頁,而後對下載的網頁進行解析,獲得咱們想要的內容。固然,這是一個爬蟲過程的一個概況,其中還有不少細節的東西須要咱們處理的,這些在後續會繼續與你們分享。服務器

 

瞭解了爬蟲的基本過程後,就能夠開始咱們真正的爬蟲之旅了。網絡

 

  • urllibsocket

 

Python有一個內置的urllib庫,可謂是爬蟲過程很是重要的一部分了。這個內置庫的使用就能夠完成向服務器發出請求並得到網頁的功能,因此也是學習爬蟲的第一步了。xss

 

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

 

首先,咱們來看看Python3.xurllib庫都有什麼吧。學習


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

控制檯下輸入以下代碼:


>>importurllib

>>dir(urllib)


結果:

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

 

能夠看到urllib除了以雙下劃線開頭結尾的內置屬性外,還有4個重要的屬性,分別是errorparserequestresponse

 

在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

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

urllib.request
response urllib.request.urlopenresult response.readresult

運行結果以下:

b'<!doctype html>\n<!--[if lt IE 7]>...</body>\n</html>\n'

發現獲得的運行結果居然是亂碼!!彆着急,這是由於編碼的問題,咱們只須要將請求的類文件讀取再解碼就能夠了。


修改代碼以下:

urllib.request
response urllib.request.urlopenresult response.read.result

運行結果:

<!doctype html>
<
!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8>..
<!--[if IE 7]>      <html class="no-js ie7 lt-ie8 lt-ie9">..
<!--[if IE 8]>      <html class="no-js ie8 lt-ie9">                 <![endif]-->
<!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"

<head>
   <
meta charset="utf-8">
...

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


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

  • urlopen

url, data, timeoutsocket._GLOBAL_DEFAULT_TI
            MEOUT,, cafile, capath, 
            cadefault, context


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


<1>url便是咱們輸入的url網址(如:http://www.xxxx.com/);

<2>data:是咱們要發給服務器請求的額外信息(好比登陸網頁須要主動填寫的用戶信息)。若是須要添加data參數,那麼是POST請求,默認無data參數時,就是GET請求;

        <2.1>通常來說,data參數只有在http協議下請求才有意義

        <2.2>data參數被規定爲byte object,也就是字節對象

        <2.3>data參數應該使用標準的結構,這個須要使用                        

         urllib.parse.urlencode()將data進行轉換,而通常咱們把data設置成字典格               式再進行轉換便可;

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

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

<4>cafile:是指向單獨文件的,包含了一系列的CA認證 (不多使用,默認便可);

<5>capath:是指向文檔目標,也是用於CA認證(不多使用,默認便可);

<5>cafile:能夠忽略

<6>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


  • Request

, url, data, headers,
                 origin_req_host, unverifiable,
                 method

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


<1>url,data和上面urlopen中的提到的同樣。

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

<3>origin_reg_host, unverifiable, method等不太經常使用


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


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


能夠經過進入瀏覽器F12查看到

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


圖片



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

urllib.request
headers response urllib.request.Request, headershtml urllib.request.urlopenresponseresult html.read.decoderesult


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


在須要headers的狀況下,使用Request對象仍是頗有必要的。

' '裏面填寫本身瀏覽器的信息便可。


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


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


  • error


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


  • URLError類

, reason, filename.args reason,
    .reason reason
    filename .filename filename

URLError類是OSError的子類,繼承OSError,沒有本身的任何行爲特色,可是將做爲error裏面全部其它類型的基類使用。


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


  • HTTPErro類

, url, code, msg, hdrs, fp.code code
    .msg msg
    .hdrs hdrs
    .fp fp
    .filename url

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


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

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



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


urllib.request
urllib.error
headers response urllib.request.Request, 
                                       headershtml urllib.request.urlopenresponseresult html.read.decodeurllib.error.URLError ee, e.reasonurllib.error.HTTPError ee, e.code


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


爲何說更加健壯了呢?


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


這些打斷程序的錯誤多是不少種,尤爲當你使用代理ip池的時候,會發生不少不一樣錯誤,這時異常就起到做用了。


  • 總結


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

  1. request基本功能, urlopen, Request

  2. error異常的使用


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

相關文章
相關標籤/搜索