網路爬蟲(四)Opener與Handler的介紹和例項應用

letflyFYF發表於2014-09-17

上一篇文章,我們提到了urllib2,今天我們將詳細講解其兩個重要概念:Openers和Handlers。


在這之前,我們先來了解一下urllib2中的兩個方法:info 和 geturl

urlopen返回的應答物件response(或者HTTPError例項)有兩個很有用的方法info()和geturl()

1.geturl():

這個返回獲取的真實的URL,這個很有用,因為urlopen(或者opener物件使用的)或許會有重定向。獲取的URL跟請求URL不同。

以人人中的一個超級連結為例,

我們建一個urllib2_test10.py來比較一下原始URL和重定向的連結:

  1. from urllib2 import Request, urlopen, URLError, HTTPError  
  2.   
  3.   
  4. old_url = 'http://rrurl.cn/b1UZuP'  
  5. req = Request(old_url)  
  6. response = urlopen(req)    
  7. print 'Old url :' + old_url  
  8. print 'Real url :' + response.geturl()

執行結果:

2.info():

這個返回物件的字典物件,該字典描述了獲取的頁面情況。通常是伺服器傳送的特定頭headers。目前是httplib.HTTPMessage例項。

經典的headers包含“Content-length”,“Content-type”,和其它內容。

我們建一個urllib2_test11.py來測試一下info的應用:

  1. from urllib2 import Request, urlopen, URLError, HTTPError  
  2.   
  3. old_url = 'http://www.baidu.com'  
  4. req = Request(old_url)  
  5. response = urlopen(req)    
  6. print 'Info():'  
  7. print response.info()

執行結果:


下面進入本章主題。

1.Openers:

當你獲取一個URL你使用一個opener(一個urllib2.OpenerDirector的例項)。

正常情況下,我們使用預設opener:通過urlopen。

但你能夠建立個性的openers。

2.Handles:

Openers使用處理器handles,所有的“繁重”工作由handlers處理。

每個handlers知道如何通過特定協議開啟URLs,或者如何處理URL開啟時的各個方面。

例如HTTP重定向或者HTTP cookies。


如果你希望用特定處理器獲取URLs你會想建立一個openers,例如獲取一個能處理cookie的opener,或者獲取一個不重定向的opener。


要建立一個opener,可以例項化一個OpenerDirector,

然後呼叫.add_handler(some_handler_instance)。

同樣,可以使用build_opener,這是一個更加方便的函式,用來建立opener物件,它只需要一次函式呼叫。

build_opener預設新增幾個處理器,但提供快捷鍵的方法來填傢伙更新預設處理器。

其它的處理器handlers你或許會希望處理代理、驗證,和其他常用但有點特殊的情況。


install_opener用來建立(全域性)預設opener。這個表示呼叫urlopen將使用你安裝的opener。

Opener物件有一個open方法。

該方法可以像urlopen函式那樣直接用來獲取urls:通常不必呼叫install_opener,除了為了方便。


說完了上面兩個內容,下面我們來看一下基本認證的內容,這裡會用到上面提及的Opener和Handler。

Basic Authentication基本驗證

為了展示建立和安裝一個handler,我們將使用HTTPBasicAuthHandler。

當需要基礎驗證時,伺服器傳送一個header(401錯誤碼)請求驗證。這個指定了scheme和一個’realm‘,看起來像這樣:www-authenticate:SCHEME realm="REALM"。

例如

www-authenticate:Basic realm="cPanel Users"

客戶端必須使用新的請求,並在請求頭裡包含正確的姓名和密碼。

這是“基礎驗證”,為了簡化這個過程,我們可以建立一個HTTPBasicAuthHandler的例項,並讓opener使用這個handler就可以啦。


HTTPBasicAuthHandler使用一個密碼管理的物件來處理URLs和realms來對映使用者名稱和密碼。

如果你知道realm(從伺服器傳送來的頭裡)是什麼,你就能使用HTTPPasswordMgr。


通常人們不關心realm是什麼。那樣的話,就能用方便的HTTPPasswordMgrWithDefaultRealm。

這個將在你為URL指定一個預設的使用者名稱和密碼。

這將在你為特定realm提供一個其它組合時得到提供。

我們通過給realm引數指定None提供給add_password來指示這種情況。


最高層次的URL是第一個要求驗證的URL。你傳給.add_password()更深層次的URLs將同樣合適。

說了這麼多廢話,下面來用一個例子演示一下上面說到的內容。

我們建一個urllib2_test12.py來測試一下info的應用:

  1. # -*- coding: utf-8 -*-  
  2. import urllib2  
  3.   
  4. # 建立一個密碼管理者  
  5. password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()  
  6.   
  7. # 新增使用者名稱和密碼  
  8.   
  9. top_level_url = "http://example.com/foo/"  
  10.   
  11. # 如果知道 realm, 我們可以使用他代替 ``None``.  
  12. # password_mgr.add_password(None, top_level_url, username, password)  
  13. password_mgr.add_password(None, top_level_url,'why''1223')  
  14.   
  15. # 建立了一個新的handler  
  16. handler = urllib2.HTTPBasicAuthHandler(password_mgr)  
  17.   
  18. # 建立 "opener" (OpenerDirector 例項)  
  19. opener = urllib2.build_opener(handler)  
  20.   
  21. a_url = 'http://www.baidu.com/'  
  22.   
  23. # 使用 opener 獲取一個URL  
  24. opener.open(a_url)  
  25.   
  26. # 安裝 opener.  
  27. # 現在所有呼叫 urllib2.urlopen 將用我們的 opener.  
  28. urllib2.install_opener(opener)  
  29.  

注意:以上的例子我們僅僅提供我們的HHTPBasicAuthHandler給build_opener。

預設的openers有正常狀況的handlers:ProxyHandler,UnknownHandler,HTTPHandler,HTTPDefaultErrorHandler, HTTPRedirectHandler,FTPHandler, FileHandler, HTTPErrorProcessor。

程式碼中的top_level_url 實際上可以是完整URL(包含"http:",以及主機名及可選的埠號)。

例如:http://example.com/。

也可以是一個“authority”(即主機名和可選的包含埠號)。

例如:“example.com” or “example.com:8080”。

後者包含了埠號。


本章主要了解了如何使用urllib2中的opener和handler這兩個工具向URL中新增使用者名稱和密碼,下章我們將詳細瞭解urllib2抓包細節。



相關文章