urllib.request --- 用于打開 URL 的可擴展庫?

源碼: Lib/urllib/request.py


urllib.request 模塊定義了適用于在各種復雜情況下打開 URL(主要為 HTTP)的函數和類 --- 例如基本認證、摘要認證、重定向、cookies 及其它。

參見

對于更高級別的 HTTP 客戶端接口,建議使用 Requests

urllib.request 模塊定義了以下函數:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)?

打開統一資源定位地址 url,可以是一個字符串或一個 Request 對象。

data 必須是一個對象,用于給出要發送到服務器的附加數據,若不需要發送數據則為 None。詳情請參閱 Request

urllib.request 模塊使用 HTTP/1.1 并且在其 HTTP 請求中包含 Connection:close 頭。

timeout 為可選參數,用于指定阻塞操作(如連接嘗試)的超時時間,單位為秒。如未指定,將使用全局默認超時參數)。本參數實際僅對 HTTP、HTTPS 和 FTP 連接有效。

如果給定了 context 參數,則必須是一個 ssl.SSLContext 實例,用于描述各種 SSL 參數。更多詳情請參閱 HTTPSConnection

cafilecapath 為可選參數,用于為 HTTPS 請求指定一組受信 CA 證書。cafile 應指向包含CA 證書的單個文件, capath 則應指向哈希證書文件的目錄。更多信息可參閱 ssl.SSLContext.load_verify_locations()

cadefault 將被忽略。

This function always returns an object which can work as a context manager and has methods such as

  • geturl() --- return the URL of the resource retrieved, commonly used to determine if a redirect was followed

  • info() --- return the meta-information of the page, such as headers, in the form of an email.message_from_string() instance (see Quick Reference to HTTP Headers)

  • getcode() -- return the HTTP status code of the response.

對于 HTTP 和 HTTPS 的 URL 而言,本函數將返回一個稍經修改的 http.client.HTTPResponse 對象。除了上述 3 個新的方法之外,還有 msg 屬性包含了與 reason 屬性相同的信息---服務器返回的原因描述文字,而不是 HTTPResponse 的文檔所述的響應頭部信息。

對于 FTP、文件、數據的URL,以及由傳統的 URLopener? 和 FancyURLopener 類處理的請求,本函數將返回一個 urllib.response.addinfourl 對象。

協議錯誤時引發 URLError

請注意,如果沒有處理函數對請求進行處理,則有可能會返回 None 。盡管默認安裝的全局 OpenerDirector 會用 UnknownHandler 來確保不會發生這種情況。

此外,如果檢測到設置了代理(比如設置了 http_proxy 之類的環境變量),默認會安裝 ProxyHandler 并確保通過代理處理請求。

Python 2.6 以下版本中留存的 urllib.urlopen 函數已停止使用了; urllib.request.urlopen() 對應于傳統的 urllib2.urlopen 。對代理服務的處理是通過將字典參數傳給 urllib.urlopen 來完成的,可以用 ProxyHandler 對象獲取到代理處理函數。

在 3.2 版更改: 增加了 cafilecapath

在 3.2 版更改: 現在如果可行(指 ssl.HAS_SNI 為真),支持 HTTPS 虛擬主機

3.2 新版功能: data 可以是一個可迭代對象。

在 3.3 版更改: 增加了 cadefault

在 3.4.3 版更改: 增加了 context

3.6 版后已移除: cafilecapathcadefault 已廢棄,轉而推薦使用 context。請改用 ssl.SSLContext.load_cert_chain() 或讓 ssl.create_default_context() 選取系統信任的 CA 證書。

urllib.request.install_opener(opener)?

安裝一個 OpenerDirector 實例,作為默認的全局打開函數。僅當 urlopen 用到該打開函數時才需要安裝;否則,只需調用 OpenerDirector.open() 而不是 urlopen()。代碼不會檢查是否真的屬于 OpenerDirector 類,所有具備適當接口的類都能適用。

urllib.request.build_opener([handler, ...])?

返回一個 OpenerDirector 實例,以給定順序把處理函數串聯起來。處理函數可以是 BaseHandler 的實例,也可以是 BaseHandler 的子類(這時構造函數必須允許不帶任何參數的調用)。以下類的實例將位于 處理函數 之前,除非 處理函數 已包含這些類、其實例或其子類: ProxyHandler (如果檢測到代理設置)、UnknownHandlerHTTPHandlerHTTPDefaultErrorHandlerHTTPRedirectHandlerFTPHandlerFileHandlerHTTPErrorProcessor

若 Python 安裝有 SLL 支持(指可以導入 ssl 模塊),亦會加入 HTTPSHandler

A BaseHandler subclass may also change its handler_order attribute to modify its position in the handlers list.

urllib.request.pathname2url(path)?

將路徑名 path 從路徑本地寫法轉換為 URL 路徑部件采用的格式。這不會生成完整的 URL。返回值將會用 quote() 函數加以編碼。

urllib.request.url2pathname(path)?

從百分號編碼的 URL 中將 path 部分轉換為本地路徑的寫法。本函數不接受完整的 URL。本函數利用 unquote() 解碼 path

urllib.request.getproxies()?

本輔助函數將返回一個字典,表示各方案映射的代理服務器 URL。本函數掃描名為 <scheme>_proxy 的環境變量,不區分大小寫,首先會考慮所有操作系統。如果環境變量無法找到,則會 從 Mac OS X 的 Mac OSX 系統配置或 Windows 系統的注冊表查找代理服務器信息。如果同時存在小寫和大寫環境變量(且內容不一致),則首選小寫。

注解

如果存在環境變量 REQUEST_METHOD ,通常表示腳本運行于 CGI 環境中,則環境變量 HTTP_PROXY (大寫的 _PROXY)將會被忽略。這是因其可以由客戶端用 HTTP 頭部信息 “Proxy:”注入。若要在 CGI 環境中使用 HTTP 代理,請顯式使用 `ProxyHandler ,或確保變量名稱為小寫(或至少是 _proxy 后綴)。

提供了以下類:

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)?

URL 請求的抽象類。

url 應該是是一個含有一個有效的統一資源定位地址的字符串。

data must be an object specifying additional data to send to the server, or None if no such data is needed. Currently HTTP requests are the only ones that use data. The supported object types include bytes, file-like objects, and iterables. If no Content-Length nor Transfer-Encoding header field has been provided, HTTPHandler will set these headers according to the type of data. Content-Length will be used to send bytes objects, while Transfer-Encoding: chunked as specified in RFC 7230, Section 3.3.1 will be used to send files and other iterables.

對于 HTTP POST 請求方法而言,data 應該是標準 application/x-www-form-urlencoded 格式的緩沖區。 urllib.parse.urlencode() 函數的參數為映射對象或二元組序列,并返回一個該編碼格式的 ASCII 字符串。在用作 data 參數之前,應將其編碼為字節串。

headers 應為字典對象,視同于用每個鍵和值作為參數去調用 add_header()。 通常用于 User-Agent 頭部數據的“偽裝” ,瀏覽器用這些頭部數據標識自己——某些 HTTP 服務器只允許來自普通瀏覽器的請求,而不接受來自腳本的請求。例如,Mozilla Firefox 可能將自己標識為 "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11",而 urllib 的默認用戶代理字符串則是 "Python-urllib/2.6" (在 Python 2.6 上)。

如果給出了 data 參數,則應當包含合適的 Content-Type 頭部信息。若未提供且 data 不是 None,則會把 Content-Type: application/x-www-form-urlencoded 加入作為默認值。

接下來的兩個參數,只對第三方 HTTP cookie 的處理才有用:

origin_req_host 應為發起初始會話的請求主機,定義參見 RFC 2965 。默認指為``http.cookiejar.request_host(self)`` 。這是用戶發起初始請求的主機名或 IP 地址。假設請求是針對 HTML 文檔中的圖片數據發起的,則本屬性應為對包含圖像的頁面發起請求的主機。

unverifiable 應該標示出請求是否無法驗證,定義參見 RFC 2965 。默認值為 False 。所謂無法驗證的請求,是指用戶沒有機會對請求的 URL 做驗證。例如,如果請求是針對 HTML 文檔中的圖像,用戶沒有機會去許可能自動讀取圖像,則本屬性應為 True。

method 應為字符串,標示要采用的 HTTP 請求方法(例如 'HEAD' )。如果給出本參數,其值會存儲在 method 屬性中,并由 get_method() 使用。如果 data 為``None`` 則默認值為 'GET' ,否則為 'POST'。子類可以設置 method 屬性來標示不同的默認請求方法。

注解

如果 data 對象無法分多次傳遞其內容(比如文件或只能生成一次內容的可迭代對象)并且由于 HTTP 重定向或身份驗證而發生請求重試行為,則該請求不會正常工作。 data 是緊挨著頭部信息發送給 HTTP 服務器的。現有庫不支持 HTTP 100-continue 的征詢。

在 3.3 版更改: Request 類增加了 Request.method 參數。

在 3.4 版更改: 默認 Request.method 可以在類中標明。

在 3.6 版更改: 如果給出了 Content-Length ,且 data 既不為 None 也不是字節串對象,則不會觸發錯誤。而會退而求其次采用分塊傳輸的編碼格式。

class urllib.request.OpenerDirector?

OpenerDirector 類通過串接在一起的 BaseHandler 打開 URL,并負責管理 handler 鏈及從錯誤中恢復。

class urllib.request.BaseHandler?

這是所有已注冊 handler 的基類,只做了簡單的注冊機制。

class urllib.request.HTTPDefaultErrorHandler?

為 HTTP 錯誤響應定義的默認 handler,所有響應都會轉為 HTTPError 異常。

class urllib.request.HTTPRedirectHandler?

一個用于處理重定向的類。

class urllib.request.HTTPCookieProcessor(cookiejar=None)?

一個用于處理 HTTP Cookies 的類。

class urllib.request.ProxyHandler(proxies=None)?

讓請求轉去代理服務。若給出了 proxies,則其必須是一個將協議名稱映射為代理 URL 的字典對象。默認是從環境變量 <protocol>_proxy 中讀取代理服務的列表。如果沒有設置代理環境變量,則 Windows 會從注冊表的 Internet 設置部分獲取代理設置,而 Mac OS X 則會從 OS X 系統配置框架中讀取代理信息。

若要禁用自動檢測出來的代理,請傳入空的字典對象。

環境變量 no_proxy 可用于指定不必通過代理訪問的主機;應為逗號分隔的主機名后綴列表,可加上 :port ,例如 cern.ch,ncsa.uiuc.edu,some.host:8080

注解

如果設置了 REQUEST_METHOD 變量,則會忽略 HTTP_PROXY ;參閱 getproxies() 文檔。

class urllib.request.HTTPPasswordMgr?

維護 (realm, uri) -> (user, password) 映射數據庫。

class urllib.request.HTTPPasswordMgrWithDefaultRealm?

維護 (realm, uri) -> (user, password) 映射數據庫。realm 為 None 視作全匹配,若沒有其他合適的安全區域就會檢索它。

class urllib.request.HTTPPasswordMgrWithPriorAuth?

HTTPPasswordMgrWithDefaultRealm 的一個變體,也帶有 uri -> is_authenticated 映射數據庫。可被 BasicAuth 處理函數用于確定立即發送身份認證憑據的時機,而不是先等待 401 響應。

3.5 新版功能.

class urllib.request.AbstractBasicAuthHandler(password_mgr=None)?

這是一個幫助完成 HTTP 身份認證的混合類,對遠程主機和代理都適用。參數 password_mgr 應與 HTTPPasswordMgr 兼容;關于必須支持哪些接口,請參閱 HTTPPasswordMgr 對象 對象的章節。如果 password_mgr 還提供 is_authenticatedupdate_authenticated 方法(請參閱 HTTPPasswordMgrWithPriorAuth 對象 對象),則 handler 將對給定 URI 用到 is_authenticated 的結果,來確定是否隨請求發送身份認證憑據。如果該 URI 的 is_authenticated 返回 True,則發送憑據。如果 is_authenticatedFalse ,則不發送憑據,然后若收到 401 響應,則使用身份認證憑據重新發送請求。如果身份認證成功,則調用 update_authenticated 設置該 URI 的 is_authenticatedTrue,這樣后續對該 URI 或其所有父 URI 的請求將自動包含該身份認證憑據。

3.5 新版功能: 增加了對 is_authenticated 的支持。

class urllib.request.HTTPBasicAuthHandler(password_mgr=None)?

處理與遠程主機的身份驗證。 password_mgr 應與 HTTPPasswordMgr 兼容;有關哪些接口是必須支持的,請參閱 HTTPPasswordMgr 對象 章節。如果給出錯誤的身份認證方式, HTTPBasicAuthHandler 將會觸發 ValueError

class urllib.request.ProxyBasicAuthHandler(password_mgr=None)?

處理有代理服務時的身份驗證。 password_mgr 應與 HTTPPasswordMgr 兼容;有關哪些接口是必須支持的,請參閱 HTTPPasswordMgr 對象 章節。

class urllib.request.AbstractDigestAuthHandler(password_mgr=None)?

這是一個幫助完成 HTTP 身份認證的混合類,對遠程主機和代理都適用。參數 password_mgr 應與 HTTPPasswordMgr 兼容;關于必須支持哪些接口,請參閱 HTTPPasswordMgr 對象 的章節。

class urllib.request.HTTPDigestAuthHandler(password_mgr=None)?

處理遠程主機的身份驗證。 password_mgr 應與 HTTPPasswordMgr 兼容;有關哪些接口是必須支持的,請參閱 HTTPPasswordMgr 對象 章節。如果同時添加了 digest 身份認證 handler 和basic 身份認證 handler,則會首先嘗試 digest 身份認證。如果 digest 身份認證再返回 40x 響應,會再發送到 basic 身份驗證 handler 進行處理。如果給出 Digest 和 Basic 之外的身份認證方式, 本 handler 方法將會觸發 ValueError

在 3.3 版更改: 碰到不支持的認證方式時,將會觸發 ValueError

class urllib.request.ProxyDigestAuthHandler(password_mgr=None)?

處理有代理服務時的身份驗證。 password_mgr 應與 HTTPPasswordMgr 兼容;有關哪些接口是必須支持的,請參閱 HTTPPasswordMgr 對象 章節。

class urllib.request.HTTPHandler?

用于打開 HTTP URL 的 handler 類。

class urllib.request.HTTPSHandler(debuglevel=0, context=None, check_hostname=None)?

用于打開 HTTPS URL 的 handler 類。contextcheck_hostname 的含義與 http.client.HTTPSConnection 的一樣。

在 3.2 版更改: 添加 contextcheck_hostname 參數。

class urllib.request.FileHandler?

打開本地文件。

class urllib.request.DataHandler?

打開數據 URL。

3.4 新版功能.

class urllib.request.FTPHandler?

打開 FTP 統一資源定位地址。

class urllib.request.CacheFTPHandler?

打開 FTP URL,并將打開的 FTP 連接存入緩存,以便最大程度減少延遲。

class urllib.request.UnknownHandler?

處理所有未知類型 URL 的兜底類。

class urllib.request.HTTPErrorProcessor?

處理出錯的 HTTP 響應。

Request 對象?

以下方法介紹了 Request 的公開接口,因此子類可以覆蓋所有這些方法。這里還定義了幾個公開屬性,客戶端可以利用這些屬性了解經過解析的請求。

Request.full_url?

傳給構造函數的原始 URL。

在 3.4 版更改.

Request.full_url 是一個帶有 setter、getter 和 deleter 的屬性。讀取 full_url 屬性將會返回分段的初始請求 URL。

Request.type?

URI 方式。

Request.host?

URI 權限,通常是整個主機,但也有可能帶有冒號分隔的端口號。

Request.origin_req_host?

請求的原始主機,不含端口。

Request.selector?

URI 路徑。若 Request 使用代理,選擇器將會是傳給代理的完整 URL。

Request.data?

請求的數據體,未給出則為 None

在 3.4 版更改: 現在如果修改 Request.data 的值,則會刪除之前設置或計算過的“Content-Length”頭部信息。

Request.unverifiable?

布爾,表明請求是否為 RFC 2965 中定義的無法證實的。

Request.method?

要采用的 HTTP 請求方法。默認為 None,表示 get_method() 將對方法進行正常處理。設置本值可以覆蓋 get_method() 中的默認處理過程,設置方式可以是在 Request 的子類中給出默認值,也可以通過 method 參數給 Request 構造函數傳入一個值。

3.3 新版功能.

在 3.4 版更改: 現在可以在子類中設置默認值;而之前只能通過構造函數參數進行設置。

Request.get_method()?

返回表示 HTTP 請求方法的字符串。如果 Request.method 不為 ,則返回其值。否則若 Request.dataNone 則返回 'GET',不為 None 則返回 'POST' 。只對 HTTP 請求有效。

在 3.3 版更改: 現在 get_method 會兼顧 Request.method 的值。

Request.add_header(key, val)?

向請求添加一項頭部信息。目前只有 HTTP handler 才會處理頭部信息,將其加入發給服務器的頭部信息列表中。請注意,同名的頭部信息只能出現一次,如果 key 發生沖突,后續的調用結果將會覆蓋先前的。目前,這并不會減少 HTTP 的功能,因為所有多次使用仍有意義的頭部信息,都有一種特定方式獲得與只用一次時相同的功能。

Request.add_unredirected_header(key, header)?

添加一個不會被加入重定向請求的頭部。

Request.has_header(header)?

返回本實例是否帶有命名頭部信息(對常規數據和非重定向數據都會檢測)。

Request.remove_header(header)?

從本請求實例中移除指定命名的頭部信息(對常規數據和非重定向數據都會檢測)。

3.4 新版功能.

Request.get_full_url()?

返回構造器中給定的 URL。

在 3.4 版更改.

返回 Request.full_url

Request.set_proxy(host, type)?

連接代理服務器,為當前請求做準備。 hosttype 將會取代本實例中的對應值,selector 將會是構造函數中給出的初始 URL。

Request.get_header(header_name, default=None)?

返回給定頭部信息的數據。如果該頭部信息不存在,返回默認值。

Request.header_items()?

返回頭部信息,形式為(名稱, 數據)的元組列表。

在 3.4 版更改: 自 3.3 起已棄用的下列方法已被刪除:add_data、has_data、get_data、get_type、get_host、get_selector、get_origin_req_host 和 is_unverifiable 。

OpenerDirector 對象?

OpenerDirector 實例有以下方法:

OpenerDirector.add_handler(handler)?

handler 應為 BaseHandler 的實例。將檢索以下類型的方法,并將其添加到對應的處理鏈中(注意 HTTP 錯誤是特殊情況)。請注意,下文中的 protocol 應替換為要處理的實際協議,例如 http_response() 將是 HTTP 協議響應處理函數。并且 type 也應替換為實際的 HTTP 代碼,例如 http_error_404() 將處理 HTTP 404 錯誤。

  • <protocol>_open() — 句柄知道如何打開 protocol URLs 的信號。

    查看 BaseHandler.<protocol>_open() 以獲取更多信息。

  • http_error_<type>() — 表明該 handler 知道如何處理代碼為 type 的 HTTP 錯誤。

    查看 BaseHandler.http_error_<nnn>() 以獲取更多信息。

  • <protocol>_error() — 句柄知道如何處理來自(非-http)*protocol* 的錯誤的信號。

  • <protocol>_request() — 句柄知道如何預處理 protocol 請求的信號。

    查看 BaseHandler.<protocol>_request() 以獲取更多信息。

  • <protocol>_response() — 句柄知道如何后處理 protocol 響應的信號。

    查看 BaseHandler.<protocol>_response() 以獲取更多信息。

OpenerDirector.open(url, data=None[, timeout])?

打開給定的 url*(可以是 request 對象或字符串),可以傳入 *data 。參數、返回值和引發的異常均與 urlopen() 相同,其實只是去調用了當前安裝的全局 OpenerDirector 中的 open() 方法。可選的 timeout 參數指定了阻塞操作(如嘗試連接)的超時值(以秒為單位)(若未指定則采用全局默認的超時設置)。實際上,超時特性僅適用于 HTTP、HTTPS 和 FTP 連接。

OpenerDirector.error(proto, *args)?

處理給定協議的錯誤。將用給定的參數(協議相關)調用已注冊的給定協議的錯誤處理程序。HTTP 協議是特殊情況,采用 HTTP 響應碼來確定具體的錯誤處理程序;請參考 handler 類的 http_error_<type>() 方法。

返回值和異常均與 urlopen() 相同。

OpenerDirector 對象分 3 個階段打開 URL:

每個階段中調用這些方法的次序取決于 handler 實例的順序。

  1. 每個具有 _request() 這類方法的 handler 都會調用本方法對請求進行預處理。

  2. 調用具有 _open() 這類方法的 handler 來處理請求。當 handler 返回非None 值(即響應)或引發異常(通常是 URLError)時,本階段結束。本階段能夠傳播異常。

    事實上,以上算法首先會嘗試名為 default_open() 的方法。 如果這些方法全都返回 None,則會對名為 <protocol>_open() 的方法重復此算法。 如果這些方法也全都返回 None,則會繼續對名為 unknown_open() 的方法重復此算法。

    請注意,這些方法的代碼可能會調用 OpenerDirector 父實例的 open()error() 方法。

  3. 每個具有 _response() 這類方法的 handler 都會調用這些方法,以對響應進行后處理。

BaseHandler 對象?

BaseHandler 對象提供了一些直接可用的方法,以及其他一些可供派生類使用的方法。以下是可供直接使用的方法:

BaseHandler.add_parent(director)?

將 director 加為父 handler。

BaseHandler.close()?

移除所有父 OpenerDirector。

以下屬性和方法僅供 BaseHandler 的子類使用:

注解

以下約定已被采納:定義 <protocol>_request()<protocol>_response() 方法的子類應命名為 *Processor;所有其他子類都應命名為 *Handler

BaseHandler.parent?

一個可用的 OpenerDirector,可用于以其他協議打開 URI,或處理錯誤。

BaseHandler.default_open(req)?

本方法在 BaseHandler 予定義,但其子類若要捕獲所有 URL 則應進行定義。

若實現了本方法,則會被父類 OpenerDirector 調用。應返回一個類文件對象,類似于 OpenerDirectoropen() 的返回值,或返回“None”。觸發的異常應為 URLError,除非發生真的異常(比如 MemoryError 就不應變為 URLError)。

本方法將會在所有協議的 open 方法之前被調用。

BaseHandler.<protocol>_open(req)

本方法在 BaseHandler 予定義,但其子類若要處理給定協議的 URL 則應進行定義。

若定義了本方法,將會被父 OpenerDirector 對象調用。返回值和 default_open() 的一樣。

BaseHandler.unknown_open(req)?

本方法在 BaseHandler 予定義,但其子類若要捕獲并打開所有未注冊 handler 的 URL,則應進行定義。

若實現了本方法,將會被 parent 屬性指向的父 OpenerDirector 調用。返回值和 default_open() 的一樣。

BaseHandler.http_error_default(req, fp, code, msg, hdrs)?

本方法在 BaseHandler 予定義,但其子類若要為所有未定義 handler 的 HTTP 錯誤提供一個兜底方法,則應進行覆蓋。OpenerDirector 會自動調用本方法,獲取錯誤信息,而通常在其他時候不應去調用。

req 會是一個 Request 對象,fp 是一個帶有 HTTP 錯誤體的文件類對象,code 是三位數的錯誤碼,msg 是供用戶閱讀的解釋信息,hdrs 則是一個包含出錯頭部信息的映射對象。

返回值和觸發的異常應與 urlopen() 的相同。

BaseHandler.http_error_<nnn>(req, fp, code, msg, hdrs)

nnn 應為三位數的 HTTP 錯誤碼。本方法在 BaseHandler 中也未予定義,但當子類的實例發生代碼為 nnn 的 HTTP 錯誤時,若方法存在則會被調用。

子類應該重寫本方法,以便能處理指定的 HTTP 錯誤。

參數、返回值和觸發的異常應與 http_error_default() 相同。

BaseHandler.<protocol>_request(req)

本方法在 BaseHandler 予定義,但其子類若要對給定協議的請求進行預處理,則應進行定義。

若實現了本方法,將會被父 OpenerDirector 調用。req 將為 Request 對象。返回值應為 Request 對象。

BaseHandler.<protocol>_response(req, response)

本方法在 BaseHandler 予定義,但其子類若要對給定協議的請求進行后處理,則應進行定義。

若實現了本方法,將會被父 OpenerDirector 調用。req 將為 Request 對象。response 應實現與 urlopen() 返回值相同的接口。返回值應實現與 urlopen() 返回值相同的接口。

HTTPRedirectHandler 對象?

注解

某些 HTTP 重定向操作需要用到本模塊的客戶端代碼。這時會觸發 HTTPError。有關各種重定向代碼的確切含義,請參閱 RFC 2616

如果 HTTPRedirectHandler 呈現的重定向 URL 不是 HTTP、HTTPS 或 FTP URL,則出于安全考慮將觸發 HTTPError 異常。

HTTPRedirectHandler.redirect_request(req, fp, code, msg, hdrs, newurl)?

返回 RequestNone 對象作為重定向行為的響應。當服務器接收到重定向請求時, http_error_30*() 方法的默認實現代碼將會調用本方法。如果確實應該發生重定向,則返回一個新的 Request 對象,使得 http_error_30*() 能重定向至 newurl。否則,若沒有 handler 會處理此 URL,則會引發 HTTPError;或者本方法不能處理但或許會有其他 handler 會處理,則返回 None

注解

本方法的默認實現代碼并未嚴格遵循 RFC 2616,即 POST 請求的 301 和 302 響應不得在未經用戶確認的情況下自動進行重定向。現實情況下,瀏覽器確實允許自動重定向這些響應,將 POST 更改為 GET ,于是默認實現代碼就復現了這種處理方式。

HTTPRedirectHandler.http_error_301(req, fp, code, msg, hdrs)?

重定向到 Location:URI: URL。 這個方法會在得到 HTTP 'moved permanently' 響應時由上級 OpenerDirector 來調用。

HTTPRedirectHandler.http_error_302(req, fp, code, msg, hdrs)?

http_error_301() 相同,不過是發生“found”響應時的調用。

HTTPRedirectHandler.http_error_303(req, fp, code, msg, hdrs)?

http_error_301() 相同,不過是發生“see other”響應時的調用。

HTTPRedirectHandler.http_error_307(req, fp, code, msg, hdrs)?

http_error_301() 相同,不過是發生“temporary redirect”響應時的調用。

HTTPCookieProcessor 對象?

HTTPCookieProcessor 的實例具備一個屬性:

HTTPCookieProcessor.cookiejar?

cookie 存放在 http.cookiejar.CookieJar 中。

ProxyHandler 對象?

ProxyHandler.<protocol>_open(request)

ProxyHandler 將為每種 protocol 準備一個 _open() 方法,在構造函數給出的 proxies 字典中包含對應的代理服務器信息。通過調用 request.set_proxy(),本方法將把請求轉為通過代理服務器,并會調用 handler 鏈中的下一個 handler 來完成對應的協議處理。

HTTPPasswordMgr 對象?

以下方法 HTTPPasswordMgrHTTPPasswordMgrWithDefaultRealm 對象均有提供。

HTTPPasswordMgr.add_password(realm, uri, user, passwd)?

uri 可以是單個 URI,也可以是 URI 列表。realmuserpasswd 必須是字符串。這使得在為 realm 和超級 URI 進行身份認證時,(user, passwd) 可用作認證令牌。

HTTPPasswordMgr.find_user_password(realm, authuri)?

為給定 realm 和 URI 獲取用戶名和密碼。如果沒有匹配的用戶名和密碼,本方法將會返回 (None, None)

對于 HTTPPasswordMgrWithDefaultRealm 對象,如果給定 realm 沒有匹配的用戶名和密碼,將搜索 realm None

HTTPPasswordMgrWithPriorAuth 對象?

這是 HTTPPasswordMgrWithDefaultRealm 的擴展,以便對那些需要一直發送認證憑證的 URI 進行跟蹤。

HTTPPasswordMgrWithPriorAuth.add_password(realm, uri, user, passwd, is_authenticated=False)?

realmuriuserpasswd 的含義與 HTTPPasswordMgr.add_password() 的相同。is_authenticated 為給定 URI 或 URI 列表設置 is_authenticated 標志的初始值。如果 is_authenticated 設為 True ,則會忽略 realm

HTTPPasswordMgr.find_user_password(realm, authuri)

HTTPPasswordMgrWithDefaultRealm 對象的相同。

HTTPPasswordMgrWithPriorAuth.update_authenticated(self, uri, is_authenticated=False)?

更新給定 uri 或 URI 列表的 is_authenticated 標志。

HTTPPasswordMgrWithPriorAuth.is_authenticated(self, authuri)?

返回給定 URI is_authenticated 標志的當前狀態。

AbstractBasicAuthHandler 對象?

AbstractBasicAuthHandler.http_error_auth_reqed(authreq, host, req, headers)?

通過獲取用戶名和密碼并重新嘗試請求,以處理身份認證請求。 authreq 應該是請求中包含 realm 的頭部信息名稱,host 指定了需要進行身份認證的 URL 和路徑,req 應為 (已失敗的) Request 對象 , headers 應該是出錯的頭部信息。

host 要么是一個認證信息(例如 "python.org" ),要么是一個包含認證信息的 URL(如``"http://python.org/"`` )。 不論是哪種格式,認證信息中都不能包含用戶信息(因此,"python.org""python.org:80" 沒問題,而 "joe:password@python.org" 則不行)。

HTTPBasicAuthHandler 對象?

HTTPBasicAuthHandler.http_error_401(req, fp, code, msg, hdrs)?

如果可用的話,請用身份認證信息重試請求。

ProxyBasicAuthHandler 對象?

ProxyBasicAuthHandler.http_error_407(req, fp, code, msg, hdrs)?

如果可用的話,請用身份認證信息重試請求。

AbstractDigestAuthHandler 對象?

AbstractDigestAuthHandler.http_error_auth_reqed(authreq, host, req, headers)?

authreq 應為請求中有關 realm 的頭部信息名稱,host 應為需要進行身份認證的主機,req 應為(已失敗的) Request 對象, headers 則應為出錯的頭部信息。

HTTPDigestAuthHandler 對象?

HTTPDigestAuthHandler.http_error_401(req, fp, code, msg, hdrs)?

如果可用的話,請用身份認證信息重試請求。

ProxyDigestAuthHandler 對象?

ProxyDigestAuthHandler.http_error_407(req, fp, code, msg, hdrs)?

如果可用的話,請用身份認證信息重試請求。

HTTPHandler 對象?

HTTPHandler.http_open(req)?

發送 HTTP 請求,根據 req.has_data() 的結果,可能是 GET 或 POST 格式。

HTTPSHandler 對象?

HTTPSHandler.https_open(req)?

發送 HTTPS 請求,根據 req.has_data() 的結果,可能是 GET 或 POST 格式。

FileHandler 對象?

FileHandler.file_open(req)?

若無主機名或主機名為 'localhost' ,則打開本地文件。

在 3.2 版更改: 本方法僅適用于本地主機名。如果給出的是遠程主機名,將會觸發 URLError?。

DataHandler 對象?

DataHandler.data_open(req)?

讀取內含數據的 URL。這種 URL 本身包含了經過編碼的數據。 RFC 2397 中給出了數據 URL 的語法定義。目前的代碼庫將忽略經過 base64 編碼的數據 URL 中的空白符,因此 URL 可以放入任何源碼文件中。如果數據 URL 的 base64 編碼尾部缺少填充,即使某些瀏覽器不介意,但目前的代碼庫仍會引發 ValueError

FTPHandler 對象?

FTPHandler.ftp_open(req)?

打開由 req 給出的 FTP 文件。登錄時的用戶名和密碼總是為空。

CacheFTPHandler 對象?

CacheFTPHandler 對象即為加入以下方法的 FTPHandler 對象:

CacheFTPHandler.setTimeout(t)?

設置連接超時為 t 秒。

CacheFTPHandler.setMaxConns(m)?

設置已緩存的最大連接數為 m

UnknownHandler 對象?

UnknownHandler.unknown_open()?

觸發 URLError?異常。

HTTPErrorProcessor 對象?

HTTPErrorProcessor.http_response(request, response)?

處理出錯的 HTTP 響應。

對于 200 錯誤碼,響應對象應立即返回。

對于 200 以外的錯誤碼,只通過 OpenerDirector.error() 將任務傳給 handler 的 http_error_<type>() 方法。如果最終沒有 handler 處理錯誤, HTTPDefaultErrorHandler 將觸發 HTTPError

HTTPErrorProcessor.https_response(request, response)?

HTTPS 出錯響應的處理。

http_response() 方法相同。

例子?

HOWTO 使用 urllib 包獲取網絡資源 中給出了更多的示例。

以下示例將讀取 python.org 主頁并顯示前 300 個字節的內容:

>>> import urllib.request
>>> with urllib.request.urlopen('http://www.python.org/') as f:
...     print(f.read(300))
...
b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n\n\n<html
xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n\n<head>\n
<meta http-equiv="content-type" content="text/html; charset=utf-8" />\n
<title>Python Programming '

請注意,urlopen 將返回字節對象。這是因為 urlopen 無法自動確定由 HTTP 服務器收到的字節流的編碼。通常,只要能確定或猜出編碼格式,就應將返回的字節對象解碼為字符串。

下述 W3C 文檔 https://www.w3.org/International/O-charset列出了可用于指明(X)HTML 或 XML 文檔編碼信息的多種方案。

python.org 網站已在 meta 標簽中指明,采用的是 utf-8 編碼,因此這里將用同樣的格式對字節串進行解碼。

>>> with urllib.request.urlopen('http://www.python.org/') as f:
...     print(f.read(100).decode('utf-8'))
...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtm

不用 context manager 方法也能獲得同樣的結果:

>>> import urllib.request
>>> f = urllib.request.urlopen('http://www.python.org/')
>>> print(f.read(100).decode('utf-8'))
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtm

以下示例將會把數據流發送給某 CGI 的 stdin,并讀取返回數據。請注意,該示例只能工作于 Python 裝有 SSL 支持的環境。

>>> import urllib.request
>>> req = urllib.request.Request(url='https://localhost/cgi-bin/test.cgi',
...                       data=b'This data is passed to stdin of the CGI')
>>> with urllib.request.urlopen(req) as f:
...     print(f.read().decode('utf-8'))
...
Got Data: "This data is passed to stdin of the CGI"

上述示例中的 CGI 代碼如下所示:

#!/usr/bin/env python
import sys
data = sys.stdin.read()
print('Content-type: text/plain\n\nGot Data: "%s"' % data)

下面是利用 Request 發送``PUT`` 請求的示例:

import urllib.request
DATA = b'some data'
req = urllib.request.Request(url='http://localhost:8080', data=DATA,method='PUT')
with urllib.request.urlopen(req) as f:
    pass
print(f.status)
print(f.reason)

基本 HTTP 認證示例:

import urllib.request
# Create an OpenerDirector with support for Basic HTTP Authentication...
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm='PDQ Application',
                          uri='https://mahler:8092/site-updates.py',
                          user='klem',
                          passwd='kadidd!ehopper')
opener = urllib.request.build_opener(auth_handler)
# ...and install it globally so it can be used with urlopen.
urllib.request.install_opener(opener)
urllib.request.urlopen('http://www.example.com/login.html')

build_opener() 默認提供了很多現成的 handler,包括 ProxyHandler。 默認情況下,ProxyHandler 會使用名為 <scheme>_proxy 的環境變量,其中的 <scheme> 是相關的 URL 協議。 例如,可以讀取 http_proxy 環境變量來獲取 HTTP 代理的 URL。

以下示例將默認的 ProxyHandler 替換為自己的 handler,由程序提供代理 URL,并利用 ProxyBasicAuthHandler 加入代理認證的支持:

proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
proxy_auth_handler.add_password('realm', 'host', 'username', 'password')

opener = urllib.request.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 urllib.request
req = urllib.request.Request('http://www.example.com/')
req.add_header('Referer', 'http://www.python.org/')
# Customize the default User-Agent header value:
req.add_header('User-Agent', 'urllib-example/0.1 (Contact: . . .)')
r = urllib.request.urlopen(req)

OpenerDirector 自動會在每個 Request 中加入一項 User-Agent 頭部信息。若要修改,請參見以下語句:

import urllib.request
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
opener.open('http://www.example.com/')

另請記得,當 Request 傳給 urlopen() (或 OpenerDirector.open())時,會加入一些標準的頭部信息( Content-LengthContent-TypeHost)。

以下會話示例用 GET 方法讀取包含參數的 URL。

>>> import urllib.request
>>> import urllib.parse
>>> params = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> url = "http://www.musi-cal.com/cgi-bin/query?%s" % params
>>> with urllib.request.urlopen(url) as f:
...     print(f.read().decode('utf-8'))
...

以下示例換用 POST 方法。請注意 urlencode 輸出結果先被編碼為字節串 data,再送入 urlopen。

>>> import urllib.request
>>> import urllib.parse
>>> data = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> data = data.encode('ascii')
>>> with urllib.request.urlopen("http://requestb.in/xrbl82xr", data) as f:
...     print(f.read().decode('utf-8'))
...

以下示例顯式指定了 HTTP 代理,以覆蓋環境變量中的設置:

>>> import urllib.request
>>> proxies = {'http': 'http://proxy.example.com:8080/'}
>>> opener = urllib.request.FancyURLopener(proxies)
>>> with opener.open("http://www.python.org") as f:
...     f.read().decode('utf-8')
...

以下示例根本不用代理,也覆蓋了環境變量中的設置:

>>> import urllib.request
>>> opener = urllib.request.FancyURLopener({})
>>> with opener.open("http://www.python.org/") as f:
...     f.read().decode('utf-8')
...

已停用的接口?

以下函數和類是由 Python 2 模塊 urllib``(相對早于 ``urllib2 )移植過來的。將來某個時候可能會停用。

urllib.request.urlretrieve(url, filename=None, reporthook=None, data=None)?

將 URL 形式的網絡對象復制為本地文件。如果 URL 指向本地文件,則必須提供文件名才會執行復制。返回值為元組 (filename, headers) ,其中 filename 是保存網絡對象的本地文件名, headers 是由 urlopen() 返回的遠程對象 info() 方法的調用結果。可能觸發的異常與 urlopen() 相同。

第二個參數指定文件的保存位置(若未給出,則會是名稱隨機生成的臨時文件)。第三個參數是個可調用對象,在建立網絡連接時將會調用一次,之后每次讀完數據塊后會調用一次。該可調用對象將會傳入 3 個參數:已傳輸的塊數、塊的大小(以字節為單位)和文件總的大小。如果面對的是老舊 FTP 服務器,文件大小參數可能會是 -1 ,這些服務器響應讀取請求時不會返回文件大小。

以下例子演示了大部分常用場景:

>>> import urllib.request
>>> local_filename, headers = urllib.request.urlretrieve('http://python.org/')
>>> html = open(local_filename)
>>> html.close()

如果 url 使用 http: 方式的標識符,則可能給出可選的 data 參數來指定一個 POST 請求 (通常的請求類型為 GET)。 data 參數必須是標準 application/x-www-form-urlencoded 格式的字節串對象;參見 urllib.parse.urlencode() 函數。

urlretrieve() 在檢測到可用數據少于預期的大小(即由 Content-Length 標頭所報告的大小)時將引發 ContentTooShortError。 例如,這可能會在下載中斷時發生。

Content-Length 會被視為大小的下限:如果存在更多的可用數據,urlretrieve 會讀取更多的數據,但是如果可用數據少于該值,則會引發異常。

在這種情況下你仍然能夠獲取已下載的數據,它會存放在異常實例的 content 屬性中。

如果未提供 Content-Length 標頭,urlretrieve 就無法檢查它所下載的數據大小,只是簡單地返回它。 在這種情況下你只能假定下載是成功的。

urllib.request.urlcleanup()?

清理之前調用 urlretrieve() 時可能留下的臨時文件。

class urllib.request.URLopener(proxies=None, **x509)?

3.3 版后已移除.

用于打開和讀取 URL 的基類。 除非你需要支持使用 http:, ftp:file: 以外的方式來打開對象,那你也許可以使用 FancyURLopener

在默認情況下,URLopener 類會發送一個內容為 urllib/VVVUser-Agent 標頭,其中 VVVurllib 的版本號。 應用程序可以通過子類化 URLopenerFancyURLopener 并在子類定義中將類屬性 version 設為適當的字符串值來定義自己的 User-Agent 標頭。

可選的 proxies 形參應當是一個將方式名稱映射到代理 URL 的字典,如為空字典則會完全關閉代理。 它的默認值為 None,在這種情況下如果存在環境代理設置則將使用它,正如上文 urlopen() 的定義中所描述的。

一些歸屬于 x509 的額外關鍵字形參可在使用 https: 方式時被用于客戶端的驗證。 支持通過關鍵字 key_filecert_file 來提供 SSL 密鑰和證書;對客戶端驗證的支持需要提供這兩個形參。

如果服務器返回錯誤代碼則 URLopener 對象將引發 OSError 異常。

open(fullurl, data=None)?

使用適當的協議打開 fullurl。 此方法會設置緩存和代理信息,然后調用適當的打開方法并附帶其輸入參數。 如果方式無法被識別,則會調用 open_unknown()data 參數的含義與 urlopen() 中的 data 參數相同。

此方法總是會使用 quote() 來對 fullurl 進行轉碼。

open_unknown(fullurl, data=None)?

用于打開未知 URL 類型的可重載接口。

retrieve(url, filename=None, reporthook=None, data=None)?

提取 url 的內容并將其存放到 filename 中。 返回值為元組,由一個本地文件名和一個包含響應標頭 (對于遠程 URL) 的 email.message.Message 對象或者 None (對于本地 URL)。 之后調用方必須打開并讀取 filename 的內容。 如果 filename 未給出并且 URL 指向一個本地文件,則會返回輸入文件名。 如果 URL 非本地并且 filename 未給出,則文件名為帶有與輸入 URL 的路徑末尾部分后綴相匹配的后綴的 tempfile.mktemp() 的輸出。 如果給出了 reporthook,它必須為接受三個數字形參的函數:數據分塊編號、讀入分塊的最大數據量和下載的總數據量 (未知則為 -1)。 它將在開始時和從網絡讀取每個數據分塊之后被調用。 對于本地 URL reporthook 會被忽略。

如果 url 使用 http: 方式的標識符,則可能給出可選的 data 參數來指定一個 POST 請求 (通常的請求類型為 GET)。 data 參數必須為標準的 application/x-www-form-urlencoded 格式 ;參見 urllib.parse.urlencode() 函數。

version?

指明打開器對象的用戶代理名稱的變量。 以便讓 urllib 告訴服務器它是某個特定的用戶代理,請在子類中將其作為類變量來設置或是在調用基類構造器之前在構造器中設置。

class urllib.request.FancyURLopener(...)?

3.3 版后已移除.

FancyURLopener 子類化了 URLopener 以提供對以下 HTTP 響應代碼的默認處理: 301, 302, 303, 307 和 401。 對于上述的 30x 響應代碼,會使用 Location 標頭來獲取實際 URL。 對于 401 響應代碼 (authentication required),則會執行基本 HTTP 驗證。 對于 30x 響應代碼,遞歸層數會受 maxtries 屬性值的限制,該值默認為 10。

對于所有其他響應代碼,會調用 http_error_default() 方法,你可以在子類中重載此方法來正確地處理錯誤。

注解

根據 RFC 2616 的說明,對 POST 請求的 301 和 302 響應不可在未經用戶確認的情況下自動進行重定向。 在現實情況下,瀏覽器確實允許自動重定義這些響應,將 POST 更改為 GET,于是 urllib 就會復現這種行為。

傳給此構造器的形參與 URLopener 的相同。

注解

當執行基本驗證時,FancyURLopener 實例會調用其 prompt_user_passwd() 方法。 默認的實現將向用戶詢問控制終端所要求的信息。 如有必要子類可以重載此方法來支持更適當的行為。

FancyURLopener 類附帶了一個額外方法,它應當被重載以提供適當的行為:

prompt_user_passwd(host, realm)?

返回指定的安全體系下在給定的主機上驗證用戶所需的信息。 返回的值應當是一個元組 (user, password),它可被用于基本驗證。

該實現會在終端上提示此信息;應用程序應當重載此方法以使用本地環境下適當的交互模型。

urllib.request 的限制?

  • 目前,僅支持下列協議: HTTP (0.9 和 1.0 版), FTP, 本地文件, 以及數據 URL。

    在 3.4 版更改: 增加了對數據URL 的支持。

  • urlretrieve() 的緩存特性已被禁用,等待有人有時間去正確地解決過期時間標頭的處理問題。

  • 應當有一個函數來查詢特定 URL 是否在緩存中。

  • 為了保持向下兼容性,如果某個 URL 看起來是指向本地文件但該文件無法被打開,則該 URL 會使用 FTP 協議來重新解讀。 這有時可能會導致令人迷惑的錯誤消息。

  • urlopen()urlretrieve() 方法在等待網絡連接建立時會導致任意長的延遲。這意味著在不使用線程的情況下,搭建一個可交互的網絡客戶端是非常困難的。

  • urlopen()urlretrieve() 返回的數據就是服務器所返回的原始數據。 這可以是二進制數據(如圖片)、純文本或 HTML 代碼等。 HTTP 協議在響應標頭中提供了類型信息,這可以通過讀取 Content-Type 標頭來查看。 如果返回的數據是 HTML,你可以使用 html.parser 模塊來解析它。

  • 處理 FTP 協議的代碼無法區分文件和目錄。 這在嘗試讀取指向不可訪問的 URL 時可能導致意外的行為。 如果 URL 以一個 / 結束,它會被認為指向一個目錄并將作相應的處理。 但是如果讀取一個文件的嘗試導致了 550 錯誤(表示 URL 無法找到或不可訪問,這常常是由于權限原因),則該路徑會被視為一個目錄以便處理 URL 是指定一個目錄但略去了末尾 / 的情況。 這在你嘗試獲取一個因其設置了讀取權限因而無法訪問的文件時會造成誤導性的結果;FTP 代碼將嘗試讀取它,因 550 錯誤而失敗,然后又為這個不可讀取的文件執行目錄列表操作。 如果需要細粒度的控制,請考慮使用 ftplib 模塊,子類化 FancyURLopener,或是修改 _urlopener 來滿足你的需求。

urllib.response --- urllib 使用的 Response 類?

The urllib.response module defines functions and classes which define a minimal file like interface, including read() and readline(). The typical response object is an addinfourl instance, which defines an info() method and that returns headers and a geturl() method that returns the url. Functions defined by this module are used internally by the urllib.request module.