###目的###
打開指定網址
urllib2.urlopen(url[, data][, timeout])
import urllibimport urllib2data = urllib.urlencode({"UserStyle":"student", "user":"zhangsan", "passWord":"123456"}) # POST 數據,非POST請求可省略urllib2.urlopen(url[, data][, timeout])OpenerDirector.open(url[, data][, timeout])
import urllibimport urllib2data = urllib.urlencode({"UserStyle":"student", "user":"zhangsan", "password":"123456"}) # POST 數據,非POST請求可省略opener = urllib2.build_opener([handler, ...])opener.open(url[, data][, timeout])附:
urllib2 模塊官方文檔翻譯 V1.1 - 二兩丶
參考鏈接:
20.6. urllib2 — extensible library for opening URLs — Python 2.7.8 documentation
注: urllib2 模塊在Python 3 中被拆分成了 urllib.request 和 urllib.error . 當你將你的代碼轉換到 Python 3 時, 2to3 工具能夠自動地幫助你調整導入的模塊
urllib2 模塊定義了在復雜的世界中幫助你打開 URL (大部分是 HTTP )的函數和類 - 包括基本和摘要式認證,重定向,cookie和更多的一些功能.
打開參數 url 中的URL, url 參數可以是字符串類型或者 Request 對象.
警告: HTTPS 請求不會驗證任何服務器的證書.
data 參數可能是指定發送到服務器的額外數據的字符串,如果沒有這樣的數據的話它將是 None .目前只有 HTTP 的請求會使用 data 參數;當提供 data 參數時, HTTP 請求會將 GET 請求替換為 POST 請求. data 參數應當是標準的 application/x-www-form-urlencoded 格式的緩沖. urllib.urlencode() 函數接受一個映射或者包含二元元組的序列作為參數并返回一個符合格式的字符串. urllib2 模塊發送包含了 Connection:close 頭的 HTTP/1.1 請求.
可選參數 timeout 指定了類似于連接嘗試的阻塞操作超時的秒數(如果沒有指定的話,將使用全局的超時設置).這個參數僅對 HTTP , HTTPS 和 FTP 連接有效.
這個函數返回一個添加了以下三個方法的類文件對象:
- **geturl()** - 返回檢索到的資源的URL,通常用于確定是否跟隨了一個重定向- **info()** - 以一個 mlmetools.Message 實例的形式返回頁面的元信息,例如頭- **getcode()** - 返回 HTTP 響應的狀態碼觸發 URLError 的錯誤.
注意如果沒有處理器處理請求(盡管默認情況下安裝全局的 OpenerDirector 使用 UnknownHandler 來確保這種情況永遠不會發生),函數可能返回None.
另外,如果檢測到代理設置(例如,當一個 *_PRoxy 環境變量被設置時,比如 http_proxy ), ProxyHandler 會被默認安裝確保處理請求使之通過代理.
安裝一個 OpenerDirector 實例作為默認的全局 opener.安裝一個 opener 僅在你希望 urlopen() 函數使用它時才是必須的;否則,簡單的調用 OpenDirector.open() 來代替 urlopen() .代碼不會檢查一個真正的 OpenerDirector , 并且任何類相應的接口都將工作.
返回一個連接了按順序給出的處理器的 Openerdirector 實例. handlers 可以是 BaseHandler 的任何實例,或者是 BaseHandler 的子類(在這種情況下它必須能夠調用沒有任何參數的結構).以下類的實例必須在 handler 之前,除非 handlers 包含了它們的實例或者他們的子類的實例: ProxyHandler (如果代理設置被檢測到), UnknownHandler , HTTPHandler , HTTPDefaultErrorHandler , HTTPRedirectHandler , FTPHandler , FileHandler , HTTPErrorProcessor.
如果安裝的 Python 支持 SSL (例如 ssl 模塊能夠被導入), HTTPHandler 也將被添加.
從 Python 2.3 開始,一個 BaseHandler 的子類也有可能改變它的 handler_order 屬性以修改它在處理器列表中的位置.
以下異常會在會在合適的情況下觸發:
處理器觸發這個錯誤(或者衍生的錯誤)當它們運行時出了一個問題.它是 IOError 的子類.
- ####reason####這個錯誤返回的原因可能是一個信息字符串或者另外一個異常實例(對遠程 URL 的 socket.error,對本地 URL 的 OSError).
盡管是一個異常( URLError 的一個子類),一個 HTTPError 也可以作為一個函數無異常的類文件返回值(與 urlopen 返回的東西一樣).這在處理特殊的 HTTP 錯誤時會非常有用,例如身份驗證的請求
- ####code####一個于 RFC 2616 標準中定義的 HTTP 狀態碼.這個數字值是 BaseHTTPServer.BaseHTTPRequestHandler.responses 狀態碼字典中對應的一個值
- ####reason####這個錯誤返回的原因可能是一個信息字符串或者另外一個異常實例
這個類是對 URL 請求的抽象.
url 應該是一個包含有效 URL 的字符串.
data 參數可能是指定發送到服務器的額外數據的字符串,如果沒有這樣的數據的話它將是 None .目前只有 HTTP 的請求會使用 data 參數;當提供 data 參數時, HTTP 請求會將 GET 請求替換為 POST 請求. data 參數應當是標準的 application/x-www-form-urlencoded 格式的緩沖. urllib2.urlencode() 函數接受一個映射或者包含二元元組的序列作為參數并返回一個符合格式的字符串.
headers 應當是一個字典,可以看作是將每個鍵和值當作參數調用 add_header() 函數. 這經常用來修改瀏覽器用來聲明自身的 User-Agent 頭 - 一些常見HTTP服務器只允許請求來自瀏覽器而不是腳本.例如,火狐瀏覽器將聲明自己為 "Mozilla/5.0 (X11; U; linux i686) Gecko/20071127 Firefox/2.0.0.11" ,同時 urllib2 的默認用戶代理字符串為 "Python-urllib/2.6" (在 Python 2.6 中)
最后兩個參數僅對正確地處理第三方 HTTP cookies 感興趣:
origin_req_host 應當是在 RFC 2965 中定義的起源事務的請求主機.它默認為 cookielib.request_host(self) .這是被用戶發起的主機名或 ip 地址.例如,如果請求是從一份 HTML 文檔中獲得一張圖像,參數就應該是獲得包含圖像的頁面的請求的請求主機.
unverfiable 應當聲明請求是否是不被驗證的,這在 RFC 2965 中被定義.它默認為 False .一個不被驗證的請求是用戶未選擇允許選項的 URL.例如,如果請求是從一份 HTML 文檔中獲得一張圖像,并且用戶未選擇選項允許自動地抓取圖像,參數便應該為 True.
這個類通過連接起來的 BasHandler 打開 URL ,它管理這些處理器鏈并且能從錯誤中恢復.
這是所有注冊過的處理器的基類 -僅僅負責處理注冊的簡單結構.
這是一個為 HTTP 錯誤響應定義的默認處理器;所有的響應都轉換成了 HTTPError 異常.
這是一個為處理重定向的類.
這是一個為處理 HTTP Cookie的類.
是請求通過代理.如果 proxies 參數被提供,它一定是一個協議名稱映射到代理地址的字典.默認從環境變量 **_proxy** 讀取到代理列表.如果沒有設置代理環境變量,在 Windows 環境中,那么從注冊表的網絡設置部分讀取代理設置,在Mac OS X環境中,從OS X系統配置框架檢索代理信息.
若要關閉自動代理檢測填入一個空字典即可.
保持一個 (realm, uri) -> (user, password) 映射數據庫
保持一個 (realm, uri) -> (user, password) 映射數據庫. 一個為None 的域被認為是匹配所有的域,它將被搜索如果沒有其他的域匹配的話.
這是一個幫助 HTTP 驗證的混入類,包括遠程主機驗證和代理驗證. password_mgr 參數如果被提供,應當是與 HTTPPasswordMgr 相兼容的;涉及到 HTTPPasswordMgr 對象部分的接口信息必須被支持.
“混入類被定義為‘一種被設計為通過繼承與其他類結合的類’,它給其他類提供可選擇的接口或功能。從實現上講,混入類要求多繼承;混入類通常是抽象類,不 能實例化?;烊腩惖淖饔迷谟冢核粌H可以提高功能的重用性,減少代碼冗余;而且還可以使相關的‘行為’集中在一個類中,而不是分布到多個類中,減少了避免 所謂的‘代碼分散’和‘代碼交織’問題,提高可維護性?!?/p>
處理遠程主機的身份驗證. password_mgr 參數如果被提供,應當是與 HTTPPasswordMgr 相兼容的; 涉及到 HTTPPasswordMgr 對象部分的接口信息必須被支持.
處理代理的驗證. password_mgr 參數如果被提供,應當是與 HTTPPasswordMgr 相兼容的;涉及到 HTTPPasswordMgr 對象部分的接口信息必須被支持.
這是一個幫助 HTTP 驗證的混入類,包括遠程主機驗證和代理驗證. password_mgr 參數如果被提供,應當是與 HTTPPasswordMgr 相兼容的;涉及到 HTTPPasswordMgr 對象部分的接口信息必須被支持.
處理遠程主機的身份驗證. password_mgr 參數如果被提供,應當是與 HTTPPasswordMgr 相兼容的;涉及到 HTTPPasswordMgr 對象部分的接口信息必須被支持.
處理代理的驗證. password_mgr 參數如果被提供,應當是與 HTTPPasswordMgr 相兼容的; 涉及到 HTTPPasswordMgr 對象部分的接口信息必須被支持.
一個用于處理 HTTP 地址打開的類.
一個用于處理 HTTPS 地址打開的類.
打開本地文件.
打開 FTP 地址.
打開 FTP 地址,保持打開的 FTP 連接緩存以減少延遲.
一個用于處理未知地址的全面的類.
處理 HTTP 響應錯誤.
以下方法描述了 Request 對象的公共接口,因此所有接口必須在子類中被覆蓋.
- Request.add_data(data)將請求數據設置為 data .除了 HTTP 處理器,其他處理器會忽略這個函數 - 并且參數應當是一個字節字符串,并且請求會由 GET 變為 POST.
- Request.get_method()返回一個指示 HTTP 請求方法的字符串.這僅對 HTTP 請求有意義,并且一般總是返回 GET 或者 POST .
- Request.has_data()檢查是否實例含有 POST 數據.
- Request.get_data()返回實例的 POST 數據.
- Request.add_header(key, val)添加額外的一個請求頭,頭通常會被除 HTTP 處理器之外的所有處理器在被添加進頭列表發送至服務器的地方忽略掉.注意,不能有兩個相同名稱的頭,并且后添加的頭會覆蓋掉之前有沖突的頭.目前來講,這并不是 HTTP 功能的缺陷,因為所有有意義的頭在使用超過兩次時會有一種方法(header-specific)只使用一個頭獲得相同的功能.
- Request.add_unredirected_header(key, header)添加一個不會被添加到重定向后的請求的頭.
- Request.has_header(header)檢查是否實例擁有參數中的頭(檢查普通的頭和不被重定向的頭).
- Request.get_full_url()返回在構造函數中傳遞的 URL .
- Request.get_type()返回 URL 的類型 - 也被稱為 scheme (注:應該是協議的意思,待測試)
- Request.get_host()返回建立連接的主機.
- Request.get_selector()返回選擇器 - URL 中發送到服務器中的部分.
- Request.get_header(header_name, default=None)返回指定頭的值.如果這個頭沒有出現將返回默認值.
- Request.header_items()返回一個包含所有請求頭的元組(header_name, header_value)列表
- Request.set_proxy(host, type)連接代理服務器以準備請求. host 和 type 將代替這些實例,并且實例的選擇器將會變成給予構造函數的原始 URL .
- Request.get_origin_req_host()返回起源事務的請求主機,這是在 RFC 2965中被定義的. 可以查看 Request 構造函數的文檔.
- Request.is_unverifiable()檢查是否請求時不被驗證的,這是在 RFC 2965中被定義的.可以查看 Request 構造函數的文檔.
OpenerDirector 對象有以下方法:
- OpenerDirector.add_handler(handler)handler 應當是一個 BaseHandler 實例.以下方法會被尋找并被添加到可能的鏈中(注意 HTTP 錯誤是特殊的情況).
- *`protocol_open`* - 信號處理程序知道如何打開 `*protocol_open*` 地址. - *`http_error_type`* - 信號處理程序知道如何處理 HTTP 錯誤碼類型. - *`protocol_error`* - 信號處理程序知道如何處理來自于協議( non-`http` )的錯誤. - *`protocol_request`* - 信號處理程序知道如何預處理協議請求. - *`protocol_response`* - 信號處理程序知道如何預處理協議響應.- OpenerDirector.open(url[, data][, timeout])打開提供的 url (可能是一個請求對象或者字符串), data 可以忽略.給予參數,返回值和觸發的異常是和 urlopen() (簡單的調用一般的全局 OpenerDirector 對象中的 open() 方法)一樣的.可選參數 timeout 指定了類似于連接嘗試的阻塞操作超時的秒數(如果沒有指定的話,將使用全局的超時設置).這個參數僅對 HTTP , HTTPS 和 FTP 連接有效.
- OpenerDirector.error(proto[, arg[, ...]])處理一個提供的協議的錯誤.這將為提供的帶有參數(指明協議詳情)的協議調用以注冊的錯誤處理器. HTTP 是一個特殊的例子,因為它使用 HTTP 響應碼來決定特定的錯誤處理器;這里指的是處理器類中的 **http_error_*()** 方法.
返回值和觸發的異常是和 urlopen() 一樣的.
OpenerDirector 對象打開地址分為三步:
每個階段的方法在哪里以何種順序被調用取決于處理器實例的順序.
1. 每個帶有命名類似于 *`protocol_request`* 方法的處理器都會調用這個方法來預處理請求. 2. 每個帶有命名類似于 *`protocol_open`* 方法的處理器都會調用這個方法來處理請求.當一個非 **None** (例如一個響應)值被返回或者出發一個異常時(通常是 **URLError** ),這個階段將會結束.異常可以傳播.實際上,以上算法首先嘗試過 default_open() 方法.如果所有的方法返回 None,算法會重復命名類似于 protocol_open 的方法.如果以上所有的方法都返回 None,算法將會重復命名為 unknown_open() 的方法.
注意,這些方法的實現可能涉及到調用父類 OpenerDirector 實例的 open() 和error() 方法。
3. 每個帶有命名類似于 *`protocol_response`* 方法的處理器都會調用這個方法來后處理響應.BaseHandler 對象提供了一些直接有效的方法,另外一些方法則是被派生類使用的.這些都是用于直接使用:
- BaseHandler.add_parent(director)Add a director as parent.
- BaseHandler.close()Remove any parents.
以下屬性和方法僅被 BaseHandler 的派生類使用.
注意: 子類對 protocol_request 和 protocol_response() 方法的命名約定為 *Processor;其它所有的命名為 *Handler.
- BaseHandler.parent一個有效的 OpenerDirector 對象,它可以被用作用一個不同的協議打開,或者處理錯誤.
- BaseHandler.default_open(req)這個方法不是在 BaseHandler 中被定義的,但是子類必須重寫它如果它們想匹配所有的地址的話.
這個方法如果執行將會被其父 OpenerDirector 調用.它的返回值應當和 OpenerDirector 中的 open() 描述的返回值一樣,是一個類文件對象,或者是 None .它應當觸發 URLError ,除非一個真正異常的事件發生了( MemoryError 不應該映射到 URLError ).
這個方法將在所有的特殊的協議打開方法前被調用.
- BaseHandler.protocol_open(req)("protocol" 應當被替換為協議名稱.)
這個方法不是在 BaseHandler 中被定義的,但是子類必須重寫它如果它們想處理特定協議的地址的話.
這個方法如果被定義,將會被其父 OpenerDirector 調用.它的返回值應當和 OpenerDirector 中的 default_open() 返回值一樣.
- BaseHandler.unknown_open(req)這個方法不是在 BaseHandler 中被定義的,但是子類必須重寫它如果它們想匹配所有未指定處理器的地址的話.
這個方法如果執行將會被其父 OpenerDirector 調用.它的返回值應當和 OpenerDirector 中的 default_open() 描述的返回值一樣.
- BaseHandler.http_error_default(req, fp, code, msg, hdrs)這個方法不是在 BaseHandler 中被定義的,但是子類必須重寫它如果它們打算提供全面的錯誤處理支持.當產生錯誤時 OpenerDirector 會自動調用它,并且在其他正常環境下不應被調用.
req 是一個 Request 對象, fp 是一個帶有 HTTP 錯誤體的類文件對象, code 是三位數錯誤碼, msg 是用戶可見的錯誤碼解釋, hdrs 是帶有頭錯誤信息的映射對象.
返回值和異常應當和 urlopen() 一致.
- BaseHandler.http_error_nnn(req, fp, code, msg, hdrs)nnn 三位 HTTP 錯誤碼.這個方法不是在 BaseHandler 中被定義的,當它存在于一個子類實例中并且一個對應的 HTTP 錯誤碼出現時它便會被調用.
子類必須重寫這個方法使之能夠處理特定的 HTTP 錯誤.
參數,返回值和觸發的異常應當和 http_error_default() 一致.
- BaseHandler.protocol_request(req)("protocol" 應當被替換為協議名稱.)
這個方法不是在 BaseHandler 中被定義的,但是子類必須定義它如果它們想預處理給定協議的請求.
這個方法如果被定義,將會被其父 OpenerDirector 調用. req 是一個 Request 對象.返回值應當是一個 Request 對象.
- BaseHandler.protocol_response(req, response)("protocol" 應當被替換為協議名稱.)
這個方法不是在 BaseHandler 中被定義的,但是子類必須定義它如果它們想預處理給定協議的響應.是一個對象,這個對象應當實現和 urlopen() 返回值一樣的接口.
HTTPRedirectHandler 對象
注意: 一些 HTTP 重定向需要模塊客戶端代碼的操作.如果是這種情況,將會觸發 HTTPError .查看 RFC 2616 可以獲得各種重定向代碼的具體含義.
HTTPRedirectHandler.redirect_request(req, fp, code, msg, hdrs, newurl)
返回一個 Request 或者 None 來響應重定向.當從服務器收到重定向時, http_error_30() 的默認實現會調用這個方法.如果要發生一個重定向,將會返回一個新的 Request 以允許 http_error_30()
執行重定向到新的地址.另外,如果沒有其它處理器嘗試處理這個地址,就會觸發 HTTPError ,或者返回 None 你不得不使用一個可能的另外的處理器[if no other handler should try to handle this URL, or return None if you can’t but another handler might.].
注意:這個方法的默認實現并未嚴格按照 RFC 2616 標準,也就是說301和302響應對
POST請求禁止在未經用戶確認的情況下自動重定向.實際上,瀏覽器會自動允許這些重定向響應,并將POST改為GET,默認實現再現了這種行為.
Location: 或者 URI: 地址.當收到 HTTP 'moved permanently' 響應時這個方法被其父 OpenerDirector 調用.HTTPRedirectHandler.http_error_307(req, fp, code, msg, hdrs)
與 http_error_301() 一樣,但是稱為 'temporary redirect' 響應.
HTTPCookieProcessor 對象
HTTPCookieProcessor 有一個屬性:
ProxyHandler 對象
protocol_open 函數,這個函數將通過調用 request.set_proxy() 修改請求使之通過代理,并且調用在處理鏈中的下一個處理器使協議生效[call the next handler in the chain to actually execute the protocol].HTTPPasswordMgr 對象
這些方法在 HTTPPasswordMgr 和 HTTPPasswordMgrWithDefaultRealm 對象可用.
(None,None) .None 域中尋找.AbstractBasicAuthHandler 對象
"python.org" )或者是一個包含授權成分的 URI .無論如何,授權都不能包含用戶信息成分(因此, "python.org" 和 "python.org:80" 是可以的, "joe:password@python.org" 則不可以).HTTPBasicAuthHandler 對象
ProxyBasicAuthHandler 對象
AbstractDigestAuthHandler 對象
HTTPDigestAuthHandler 對象
ProxyDigestAuthHandler 對象
HTTPHandler 對象
req.has_data().HTTPSHandler 對象
req.has_data().FileHandler 對象
CacheFTPHandler 對象
CacheFTPHandler 對象相對 FTPHandler 對象有兩個額外的方法:
UnknownHandler 對象
HTTPErrorProcessor 對象
protocol_error_code 處理方法.最終,如果沒有其他處理器處理錯誤的話, urllib2.HTTPDefaultErrorHandler 將會觸發一個 HTTPError .獲取 python.org 主頁并顯示前100個字節的例子:
import urllib2f = urllib2.urlopen('http://www.python.org/')print f.read(100)在這里我們發送一個數據包到 CGI 的標準輸入并且讀取它返回給我們的數據.注意例子僅僅在 Python 程序支持 SSL 的條件下才能正常工作.
import urllib2req = urllib2.Request(url='https://localhost/cgi-bin/test.cgi', data='This data is passed to stdin of the CGI')f = urllib2.urlopen(req)print f.read()上例示例 CGI 使用的代碼:
#!/usr/bin/env pythonimport sysdata = sys.stdin.read()print 'Content-type: text-plain/n/nGot Data: "%s"' % data使用基本的 HTTP 驗證:
import urllib2# Create an OpenerDirector with support for Basic HTTP Authentication...auth_handler = urllib2.HTTPBasicAuthHandler()auth_handler.add_password(realm='PDQ Application', uri='https://mahler:8092/site-updates.py', user='klem', passwd='kadidd!ehopper')opener = urllib2.build_opener(auth_handler)# ...and install it globally so it can be used with urlopen.urllib2.install_opener(opener)urllib2.urlopen('http://www.example.com/login.html')build_opener() 提供了許多默認處理器,包括了一個 ProxyHandler .默認地, ProxyHandler 使用名稱為 <scheme>_proxy 的環境變量, <scheme> 是相關的地址方案.例如, http_proxy 環境變量被讀取以獲得 HTTP 代理的地址.
這個例子替換了默認的 ProxyHandler,使用了一個帶有編程支持的代理地址的對象,并且使用 ProxyBasicAuthHandler 添加了代理認證支持.
proxy_handler = urllib2.ProxyHandler({'http': 'http://www.example.com:3128/'})proxy_auth_handler = urllib2.ProxyBasicAuthHandler()proxy_auth_handler.add_password('realm', 'host', 'username', 'password') opener = urllib2.build_opener(proxy_handler, proxy_auth_handler)# This time, rather than install the OpenerDirector, we use it directly:opener.open('http://www.example.com/login.html')添加 HTTP 頭:
在 Request 構造函數中使用 headers 參數,或者:
import urllib2req = urllib2.Request('http://www.example.com/')req.add_header('Referer', 'http://www.python.org/')r = urllib2.urlopen(req)OpenerDirector 自動地添加 User-Agent 頭到每一個 Request 中.為了改變它:
import urllib2opener = urllib2.build_opener()opener.addheaders = [('User-agent', 'Mozilla/5.0')]opener.open('http://www.example.com/')另外要記住的是,當 Request 傳遞到 urlopen() (或者 OpenerDirector.open())時,一些標準頭(Content-Length, Content-Type and Host)也會被添加.
新聞熱點
疑難解答