urllib.request — 用於開啟 URL 的可擴充套件庫

原始碼: Lib/urllib/request.py


urllib.request 模組定義了函式和類,有助於在一個複雜的世界中開啟 URL(主要是 HTTP),包括基本和摘要認證、重定向、cookie 等。

參見

建議使用 Requests 包 獲取更高級別的 HTTP 客戶端介面。

警告

在 macOS 上,在使用了 os.fork() 的程式中使用此模組是不安全的,因為 macOS 的 getproxies() 實現使用了更高級別的系統 API。將環境變數 no_proxy 設定為 * 以避免此問題(例如 os.environ["no_proxy"] = "*")。

可用性:非 WASI。

此模組在 WebAssembly 上不起作用或不可用。有關更多資訊,請參閱 WebAssembly 平臺

urllib.request 模組定義了以下函式:

urllib.request.urlopen(url, data=None, [timeout, ]*, context=None)

開啟 *url*,它可以是包含有效、正確編碼的 URL 的字串,也可以是 Request 物件。

*data* 必須是一個指定要傳送到伺服器的附加資料的物件,如果不需要此類資料,則為 None。有關詳細資訊,請參閱 Request

urllib.request 模組使用 HTTP/1.1 並在其 HTTP 請求中包含 Connection:close 頭部。

可選的 *timeout* 引數指定阻塞操作(如連線嘗試)的超時時間(以秒為單位)(如果未指定,將使用全域性預設超時設定)。這實際上只適用於 HTTP、HTTPS 和 FTP 連線。

如果指定了 *context*,它必須是一個 ssl.SSLContext 例項,描述各種 SSL 選項。有關詳細資訊,請參閱 HTTPSConnection

此函式始終返回一個可以作為 context manager 工作的物件,並具有 *url*、*headers* 和 *status* 屬性。有關這些屬性的更多詳細資訊,請參閱 urllib.response.addinfourl

對於 HTTP 和 HTTPS URL,此函式返回一個經過輕微修改的 http.client.HTTPResponse 物件。除了上述三個新方法外,msg 屬性包含與 reason 屬性相同的資訊 — 伺服器返回的原因短語 — 而不是 HTTPResponse 文件中指定的響應頭部。

對於 FTP、檔案和資料 URL,此函式返回 urllib.response.addinfourl 物件。

協議錯誤時會引發 URLError

請注意,如果沒有處理程式處理請求,可能會返回 None(儘管預設安裝的全域性 OpenerDirector 使用 UnknownHandler 以確保這種情況永遠不會發生)。

此外,如果檢測到代理設定(例如,當設定了 *_proxy 環境變數,如 http_proxy),ProxyHandler 會預設安裝並確保請求透過代理處理。

Python 2.6 及更早版本中的傳統 urllib.urlopen 函式已停用;urllib.request.urlopen() 對應於舊的 urllib2.urlopen。代理處理,曾經透過將字典引數傳遞給 urllib.urlopen 來完成,現在可以透過使用 ProxyHandler 物件來實現。

預設的 opener 會使用請求物件中的 fullurldataheadersmethod 引數引發一個 審計事件 urllib.Request

3.2 版中已更改: 增加了 *cafile* 和 *capath*。

現在如果可能(即如果 ssl.HAS_SNI 為真),HTTPS 虛擬主機將得到支援。

*data* 可以是可迭代物件。

3.3 版中已更改: 增加了 *cadefault*。

3.4.3 版中已更改: 增加了 *context*。

3.10 版中已更改: 如果未給出 *context*,HTTPS 連線現在會發送帶有協議指示符 http/1.1 的 ALPN 擴充套件。自定義 *context* 應使用 set_alpn_protocols() 設定 ALPN 協議。

3.13 版中已更改: 移除了 *cafile*、*capath* 和 *cadefault* 引數:請改用 *context* 引數。

urllib.request.install_opener(opener)

安裝一個 OpenerDirector 例項作為預設的全域性 opener。只有當你希望 urlopen 使用該 opener 時才需要安裝一個 opener;否則,只需呼叫 OpenerDirector.open() 而不是 urlopen()。程式碼不會檢查真正的 OpenerDirector,任何具有適當介面的類都可以工作。

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

返回一個 OpenerDirector 例項,它按給定順序連結處理程式。*handler* 可以是 BaseHandler 的例項,或者是 BaseHandler 的子類(在這種情況下,必須能夠在不帶任何引數的情況下呼叫建構函式)。以下類的例項將在 *handler* 之前,除非 *handler* 包含它們、它們的例項或它們的子類:ProxyHandler(如果檢測到代理設定)、UnknownHandlerHTTPHandlerHTTPDefaultErrorHandlerHTTPRedirectHandlerFTPHandlerFileHandlerHTTPErrorProcessor

如果 Python 安裝支援 SSL(即如果可以匯入 ssl 模組),則還會新增 HTTPSHandler

一個 BaseHandler 子類也可以更改其 handler_order 屬性來修改其在處理程式列表中的位置。

urllib.request.pathname2url(path, *, add_scheme=False)

將給定的本地路徑轉換為 file: URL。此函式使用 quote() 函式編碼路徑。

如果 *add_scheme* 為 false (預設值),則返回值省略 file: 方案字首。將 *add_scheme* 設定為 true 以返回完整的 URL。

此示例顯示了該函式在 Windows 上的使用

>>> from urllib.request import pathname2url
>>> path = 'C:\\Program Files'
>>> pathname2url(path, add_scheme=True)
'file:///C:/Program%20Files'

3.14 版中已更改: Windows 驅動器磁碟機代號不再轉換為大寫,並且不跟隨驅動器磁碟機代號的 : 字元在 Windows 上不再引發 OSError 異常。

3.14 版中已更改: 以斜槓開頭的路徑將轉換為帶有授權部分的 URL。例如,路徑 /etc/hosts 將轉換為 URL ///etc/hosts

3.14 版中已更改: 添加了 *add_scheme* 引數。

urllib.request.url2pathname(url, *, require_scheme=False, resolve_host=False)

將給定的 file: URL 轉換為本地路徑。此函式使用 unquote() 解碼 URL。

如果 *require_scheme* 為假(預設值),則給定值應省略 file: 方案字首。如果 *require_scheme* 設定為真,則給定值應包含字首;如果它不包含,則會引發 URLError

如果 URL 授權為空、localhost 或本地主機名,則會丟棄。否則,如果 *resolve_host* 設定為真,則使用 socket.gethostbyname() 解析授權並在匹配本地 IP 地址時丟棄(根據 RFC 8089 §3)。如果授權仍未處理,則在 Windows 上返回 UNC 路徑,在其他平臺上引發 URLError

此示例顯示了該函式在 Windows 上的使用

>>> from urllib.request import url2pathname
>>> url = 'file:///C:/Program%20Files'
>>> url2pathname(url, require_scheme=True)
'C:\\Program Files'

3.14 版中已更改: Windows 驅動器磁碟機代號不再轉換為大寫,並且不跟隨驅動器磁碟機代號的 : 字元在 Windows 上不再引發 OSError 異常。

3.14 版中已更改: 如果 URL 授權與本地主機名匹配,則會丟棄。否則,如果授權不為空或 localhost,則在 Windows 上返回 UNC 路徑(與之前一樣),在其他平臺上引發 URLError

3.14 版中已更改: 如果存在,則丟棄 URL 查詢和片段元件。

3.14 版中已更改: 添加了 *require_scheme* 和 *resolve_host* 引數。

urllib.request.getproxies()

此輔助函式返回一個方案到代理伺服器 URL 對映的字典。它首先以不區分大小寫的方式掃描所有作業系統中名為 <scheme>_proxy 的變數,如果找不到,則從 macOS 的系統配置和 Windows 的系統登錄檔中查詢代理資訊。如果同時存在小寫和大寫環境變數(且不一致),則優先使用小寫。

備註

如果設定了環境變數 REQUEST_METHOD(通常表示您的指令碼正在 CGI 環境中執行),則會忽略環境變數 HTTP_PROXY(大寫 _PROXY)。這是因為該變數可以由客戶端使用“Proxy:”HTTP 頭部注入。如果您需要在 CGI 環境中使用 HTTP 代理,請明確使用 ProxyHandler,或者確保變數名是小寫(或至少是 _proxy 字尾)。

提供了以下類:

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

這個類是 URL 請求的抽象。

*url* 應該是一個包含有效、正確編碼的 URL 的字串。

*data* 必須是一個指定要傳送到伺服器的附加資料的物件,如果不需要此類資料,則為 None。目前只有 HTTP 請求使用 *data*。支援的物件型別包括位元組、類檔案物件和位元組類物件的可迭代物件。如果未提供 Content-LengthTransfer-Encoding 頭部欄位,HTTPHandler 將根據 *data* 的型別設定這些頭部。Content-Length 將用於傳送位元組物件,而 Transfer-Encoding: chunked(如 RFC 7230,第 3.3.1 節所述)將用於傳送檔案和其他可迭代物件。

對於 HTTP POST 請求方法,*data* 應該是標準 application/x-www-form-urlencoded 格式的緩衝區。urllib.parse.urlencode() 函式接受一個對映或 2 元組序列,並以這種格式返回一個 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 屬性來指示不同的預設方法。

備註

如果資料物件無法多次傳遞其內容(例如,只能生成一次內容的檔案或可迭代物件),並且請求因 HTTP 重定向或認證而重試,則請求將無法按預期工作。*data* 在頭部之後立即傳送到 HTTP 伺服器。庫不支援 100-continue 期望。

3.3 版中已更改: Request.method 引數已新增到 Request 類中。

3.4 版中已更改: 預設的 Request.method 現在可以在類級別設定。

3.6 版中已更改: 如果未提供 Content-Length 且 *data* 既不是 None 也不是位元組物件,則不再引發錯誤。改為回退使用分塊傳輸編碼。

class urllib.request.OpenerDirector

OpenerDirector 類透過連結的 BaseHandler 開啟 URL。它管理處理程式的連結和錯誤的恢復。

class urllib.request.BaseHandler

這是所有已註冊處理程式的基類——並且只處理簡單的註冊機制。

class urllib.request.HTTPDefaultErrorHandler

一個類,它定義了 HTTP 錯誤響應的預設處理程式;所有響應都轉換為 HTTPError 異常。

class urllib.request.HTTPRedirectHandler

一個處理重定向的類。

class urllib.request.HTTPCookieProcessor(cookiejar=None)

一個處理 HTTP Cookie 的類。

class urllib.request.ProxyHandler(proxies=None)

使請求透過代理。如果給出了 *proxies*,它必須是一個將協議名稱對映到代理 URL 的字典。預設是從環境變數 <protocol>_proxy 讀取代理列表。如果未設定代理環境變數,則在 Windows 環境中,代理設定從登錄檔的 Internet 設定部分獲取,在 macOS 環境中,代理資訊從系統配置框架中檢索。

要停用自動檢測代理,請傳入一個空字典。

環境變數 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) 對映的資料庫。如果其他領域不適用,則將 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 物件 一節。如果 *passwd_mgr* 也提供 is_authenticatedupdate_authenticated 方法(參見 HTTPPasswordMgrWithPriorAuth 物件),則處理程式將使用給定 URI 的 is_authenticated 結果來確定是否隨請求傳送認證憑據。如果 is_authenticated 對 URI 返回 True,則傳送憑據。如果 is_authenticatedFalse,則不傳送憑據,然後如果收到 401 響應,則使用認證憑據重新發送請求。如果認證成功,則呼叫 update_authenticated 將 URI 的 is_authenticated 設定為 True,以便後續對 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 物件 一節。

3.14 版中已更改: 增加了對 HTTP 摘要認證演算法 SHA-256 的支援。

class urllib.request.HTTPDigestAuthHandler(password_mgr=None)

處理與遠端主機的認證。如果給出 *password_mgr*,它應該與 HTTPPasswordMgr 相容;有關必須支援的介面的資訊,請參閱 HTTPPasswordMgr 物件 一節。當同時新增摘要認證處理程式和基本認證處理程式時,始終首先嚐試摘要認證。如果摘要認證再次返回 40x 響應,則將其傳送到基本認證處理程式進行處理。此處理程式方法在遇到除摘要或基本以外的認證方案時將引發 ValueError

3.3 版中已更改: 在不支援的認證方案上引發 ValueError

class urllib.request.ProxyDigestAuthHandler(password_mgr=None)

處理與代理的認證。如果給出 *password_mgr*,它應該與 HTTPPasswordMgr 相容;有關必須支援的介面的資訊,請參閱 HTTPPasswordMgr 物件 一節。

class urllib.request.HTTPHandler

一個處理開啟 HTTP URL 的類。

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

一個處理開啟 HTTPS URL 的類。*context* 和 *check_hostname* 具有與 http.client.HTTPSConnection 中相同的含義。

3.2 版中已更改: 增加了 *context* 和 *check_hostname*。

class urllib.request.FileHandler

開啟本地檔案。

class urllib.request.DataHandler

開啟資料 URL。

在 3.4 版本加入。

class urllib.request.FTPHandler

開啟 FTP URL。

class urllib.request.CacheFTPHandler

開啟 FTP URL,並維護開啟的 FTP 連線快取以最大程度地減少延遲。

class urllib.request.UnknownHandler

一個處理未知 URL 的通用類。

class urllib.request.HTTPErrorProcessor

處理 HTTP 錯誤響應。

請求物件

以下方法描述了 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() 將正常計算要使用的方法。可以透過在 Request 子類中在類級別設定它來提供預設值(從而覆蓋 get_method() 中的預設計算),或者透過 *method* 引數將值傳遞給 Request 建構函式來設定。

在 3.3 版本加入。

3.4 版中已更改: 現在可以在子類中設定預設值;以前只能透過建構函式引數設定。

Request.get_method()

返回一個字串,指示 HTTP 請求方法。如果 Request.method 不是 None,則返回其值,否則如果 Request.dataNone,則返回 'GET',如果不是,則返回 'POST'。這僅對 HTTP 請求有意義。

3.3 版中已更改: get_method 現在會檢視 Request.method 的值。

Request.add_header(key, val)

向請求新增另一個頭部。目前,除 HTTP 處理程式外,所有處理程式都忽略頭部,在 HTTP 處理程式中,它們被新增到傳送到伺服器的頭部列表中。請注意,不能有多個同名頭部,如果 *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)

透過連線到代理伺服器來準備請求。*host* 和 *type* 將替換例項的那些屬性,並且例項的選擇器將是建構函式中給定的原始 URL。

Request.get_header(header_name, default=None)

返回給定頭部的值。如果頭部不存在,則返回預設值。

Request.header_items()

返回一個包含請求頭部 (header_name, header_value) 元組的列表。

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* URL。

    有關詳細資訊,請參閱 BaseHandler.<protocol>_open()

  • http_error_<type>() — 表示處理程式知道如何處理 HTTP 錯誤程式碼為 *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*(可以是請求物件或字串),可選地傳遞給定的 *data*。引數、返回值和引發的異常與 urlopen() 的相同(它只是呼叫當前安裝的全域性 OpenerDirector 上的 open() 方法)。可選的 *timeout* 引數指定阻塞操作(如連線嘗試)的超時時間(以秒為單位)(如果未指定,將使用全域性預設超時設定)。超時功能實際上只適用於 HTTP、HTTPS 和 FTP 連線。

OpenerDirector.error(proto, *args)

處理給定協議的錯誤。這將使用給定引數(特定於協議)呼叫給定協議的已註冊錯誤處理程式。HTTP 協議是一個特殊情況,它使用 HTTP 響應程式碼來確定特定的錯誤處理程式;請參閱處理程式類的 http_error_<type>() 方法。

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

OpenerDirector 物件分三個階段開啟 URL:

在每個階段中呼叫這些方法的順序由處理程式例項的排序決定。

  1. 每個具有名為 <protocol>_request() 的方法的處理程式都會呼叫該方法來預處理請求。

  2. 命名為 <protocol>_open() 的處理器被呼叫來處理請求。當處理器返回一個非 None 值(即一個響應),或者引發一個異常(通常是 URLError)時,此階段結束。異常允許傳播。

    實際上,上述演算法首先嚐試名為 default_open() 的方法。如果所有此類方法都返回 None,則演算法將對名為 <protocol>_open() 的方法重複執行。如果所有此類方法都返回 None,則演算法將對名為 unknown_open() 的方法重複執行。

    請注意,這些方法的實現可能涉及呼叫父 OpenerDirector 例項的 open()error() 方法。

  3. 每個具有名為 <protocol>_response() 方法的處理器都會呼叫該方法來後處理響應。

BaseHandler 物件

BaseHandler 物件提供了一些直接有用的方法,以及一些供派生類使用的方法。這些方法旨在直接使用

BaseHandler.add_parent(director)

新增一個 director 作為父級。

BaseHandler.close()

移除所有父級。

以下屬性和方法應僅由 BaseHandler 的派生類使用。

備註

已採用的約定是:定義 <protocol>_request()<protocol>_response() 方法的子類命名為 *Processor;所有其他子類命名為 *Handler

BaseHandler.parent

一個有效的 OpenerDirector,可用於使用不同協議開啟或處理錯誤。

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 定義,但如果子類想要捕獲所有沒有特定註冊處理器來開啟的 URL,則應定義它。

此方法如果實現,將由 parent OpenerDirector 呼叫。返回值應與 default_open() 相同。

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

此方法在 BaseHandler 定義,但如果子類打算為其他未處理的 HTTP 錯誤提供一個通用處理,則應重寫它。它將由收到錯誤的 OpenerDirector 自動呼叫,通常不應在其他情況下呼叫。

OpenerDirector 將使用五個位置引數呼叫此方法

  1. 一個 Request 物件,

  2. 一個帶有 HTTP 錯誤正文的檔案類物件,

  3. 錯誤的三位數字程式碼,作為字串,

  4. 使用者可見的程式碼解釋,作為字串,以及

  5. 錯誤頭,作為對映物件。

返回值和引發的異常應與 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 收到一個不是 HTTP、HTTPS 或 FTP URL 的重定向 URL,則會作為安全考慮引發 HTTPError 異常。

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

響應重定向返回 RequestNone。當從伺服器收到重定向時,http_error_30*() 方法的預設實現會呼叫此方法。如果應該發生重定向,則返回一個新的 Request,以允許 http_error_30*() 執行重定向到 newurl。否則,如果沒有其他處理器應該嘗試處理此 URL,則引發 HTTPError,或者如果無法處理但其他處理器可能可以處理,則返回 None

備註

此方法的預設實現並未嚴格遵循 RFC 2616,該 RFC 規定對 POST 請求的 301 和 302 響應不得在未經使用者確認的情況下自動重定向。實際上,瀏覽器確實允許這些響應的自動重定向,將 POST 更改為 GET,並且預設實現再現了這種行為。

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

重定向到 Location:URI: URL。當收到 HTTP“永久移動”響應時,父 OpenerDirector 會呼叫此方法。

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

http_error_301() 相同,但用於“找到”響應。

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

http_error_301() 相同,但用於“檢視其他”響應。

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

http_error_301() 相同,但用於“臨時重定向”響應。它不允許將請求方法從 POST 更改為 GET

HTTPRedirectHandler.http_error_308(req, fp, code, msg, hdrs)

http_error_301() 相同,但用於“永久重定向”響應。它不允許將請求方法從 POST 更改為 GET

在 3.11 版本中新增。

HTTPCookieProcessor 物件

HTTPCookieProcessor 例項有一個屬性

HTTPCookieProcessor.cookiejar

儲存 cookie 的 http.cookiejar.CookieJar

ProxyHandler 物件

ProxyHandler.<protocol>_open(request)

ProxyHandler 將為建構函式中給定 proxies 字典中具有代理的每個 protocol 提供一個 <protocol>_open() 方法。該方法將透過呼叫 request.set_proxy() 來修改請求以透過代理,並呼叫鏈中的下一個處理器來實際執行協議。

HTTPPasswordMgr 物件

這些方法適用於 HTTPPasswordMgrHTTPPasswordMgrWithDefaultRealm 物件。

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

uri 可以是單個 URI,也可以是 URI 序列。realmuserpasswd 必須是字串。這會導致當給定 realm 和任何給定 URI 的超 URI 的身份驗證時,使用 (user, passwd) 作為身份驗證令牌。

HTTPPasswordMgr.find_user_password(realm, authuri)

獲取給定領域和 URI 的使用者/密碼,如果存在。如果沒有匹配的使用者/密碼,此方法將返回 (None, None)

對於 HTTPPasswordMgrWithDefaultRealm 物件,如果給定的 realm 沒有匹配的使用者/密碼,則會搜尋 None 領域。

HTTPPasswordMgrWithPriorAuth 物件

此密碼管理器擴充套件了 HTTPPasswordMgrWithDefaultRealm 以支援跟蹤應始終傳送身份驗證憑據的 URI。

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

realmuriuserpasswdHTTPPasswordMgr.add_password() 相同。is_authenticated 設定給定 URI 或 URI 列表的 is_authenticated 標誌的初始值。如果 is_authenticated 指定為 True,則忽略 realm

HTTPPasswordMgrWithPriorAuth.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 應該是請求中包含領域資訊的頭名稱,host 指定要進行身份驗證的 URL 和路徑,req 應該是一個(失敗的)Request 物件,headers 應該是錯誤頭。

host 可以是權威機構(例如 "python.org"),也可以是包含權威元件的 URL(例如 "https://python.club.tw/")。在這兩種情況下,權威機構都不得包含使用者資訊元件(因此,"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 應該是請求中包含領域資訊的頭名稱,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 請求,它可以是 GET 或 POST,具體取決於 req.data

HTTPSHandler 物件

HTTPSHandler.https_open(req)

傳送一個 HTTPS 請求,它可以是 GET 或 POST,具體取決於 req.data

FileHandler 物件

FileHandler.file_open(req)

如果不存在主機名,或者主機名是 'localhost',則在本地開啟檔案。

3.2 版本中已更改: 此方法僅適用於本地主機名。當給出遠端主機名時,會引發 URLError

DataHandler 物件

DataHandler.data_open(req)

讀取資料 URL。這種 URL 包含編碼在 URL 本身中的內容。資料 URL 語法在 RFC 2397 中指定。此實現在 base64 編碼資料 URL 中忽略空格,因此 URL 可能會在其原始檔中換行。但儘管有些瀏覽器不介意 base64 編碼資料 URL 末尾缺少填充,此實現在這種情況下會引發 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() 將任務傳遞給 http_error_<type>() 處理器方法。最終,如果沒有其他處理器處理該錯誤,HTTPDefaultErrorHandler 將引發 HTTPError

HTTPErrorProcessor.https_response(request, response)

處理 HTTPS 錯誤響應。

行為與 http_response() 相同。

示例

除了下面的示例,如何使用 urllib 包獲取網際網路資源 中還提供了更多示例。

此示例獲取 python.org 主頁並顯示其前 300 位元組。

>>> import urllib.request
>>> with urllib.request.urlopen('https://python.club.tw/') as f:
...     print(f.read(300))
...
b'<!doctype html>\n<!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->\n<!--[if IE 7]>      <html class="no-js ie7 lt-ie8 lt-ie9">          <![endif]-->\n<!--[if IE 8]>      <html class="no-js ie8 lt-ie9">

請注意,urlopen 返回一個位元組物件。這是因為 urlopen 無法自動確定從 HTTP 伺服器接收到的位元組流的編碼。通常,程式會在確定或猜測出適當的編碼後,將返回的位元組物件解碼為字串。

以下 HTML 規範文件 https://html.spec.whatwg.org/#charset 列出了 HTML 或 XML 文件可能指定其編碼資訊的各種方式。

有關更多資訊,請參閱 W3C 文件:https://www.w3.org/International/questions/qa-html-encoding-declarations

由於 python.org 網站在其 meta 標籤中指定使用 *utf-8* 編碼,因此我們將使用相同的編碼來解碼位元組物件。

>>> with urllib.request.urlopen('https://python.club.tw/') as f:
...     print(f.read(100).decode('utf-8'))
...
<!doctype html>
<!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->
<!-

也可以不使用 上下文管理器 方法實現相同的結果。

>>> import urllib.request
>>> f = urllib.request.urlopen('https://python.club.tw/')
>>> try:
...     print(f.read(100).decode('utf-8'))
... finally:
...     f.close()
...
<!doctype html>
<!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->
<!--

在以下示例中,我們將資料流傳送到 CGI 的 stdin,並讀取它返回給我們的資料。請注意,此示例僅在 Python 安裝支援 SSL 時才有效。

>>> import urllib.request
>>> req = urllib.request.Request(url='https:///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='https://: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)
with urllib.request.urlopen('http://www.example.com/login.html') as f:
    print(f.read().decode('utf-8'))

build_opener() 預設提供了許多處理器,包括一個 ProxyHandler。預設情況下,ProxyHandler 使用名為 <scheme>_proxy 的環境變數,其中 <scheme> 是涉及的 URL 方案。例如,讀取 http_proxy 環境變數以獲取 HTTP 代理的 URL。

此示例將預設的 ProxyHandler 替換為一個使用程式設計方式提供的代理 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:
with opener.open('http://www.example.com/login.html') as f:
   print(f.read().decode('utf-8'))

新增 HTTP 標頭

使用 Request 建構函式的 *headers* 引數,或者

import urllib.request
req = urllib.request.Request('http://www.example.com/')
req.add_header('Referer', 'https://python.club.tw/')
# Customize the default User-Agent header value:
req.add_header('User-Agent', 'urllib-example/0.1 (Contact: . . .)')
with urllib.request.urlopen(req) as f:
    print(f.read().decode('utf-8'))

OpenerDirector 會自動為每個 Request 新增一個 *User-Agent* 標頭。要更改此設定

import urllib.request
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
with opener.open('http://www.example.com/') as f:
   print(f.read().decode('utf-8'))

另外,請記住,當 Request 傳遞給 urlopen() (或 OpenerDirector.open())時,會新增一些標準標頭(*Content-Length*、*Content-Type* 和 *Host*)。

這是一個使用 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 輸出的引數在傳送到 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.build_opener(urllib.request.ProxyHandler(proxies))
>>> with opener.open("https://python.club.tw") as f:
...     f.read().decode('utf-8')
...

以下示例完全不使用代理,覆蓋環境設定。

>>> import urllib.request
>>> opener = urllib.request.build_opener(urllib.request.ProxyHandler({}}))
>>> with opener.open("https://python.club.tw/") 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 是可以在其中找到物件的本地檔名,headersurlopen() 返回的物件(對於遠端物件)的 info() 方法返回的任何內容。異常與 urlopen() 相同。

第二個引數(如果存在)指定要複製到的檔案位置(如果不存在,位置將是生成名稱的臨時檔案)。第三個引數(如果存在)是一個可呼叫物件,它將在建立網路連線時被呼叫一次,此後在讀取每個塊後被呼叫一次。可呼叫物件將傳遞三個引數;已傳輸的塊數、塊大小(以位元組為單位)和檔案的總大小。在不返回檔案大小的舊版 FTP 伺服器上,第三個引數可能為 -1

以下示例說明了最常見的用法場景

>>> import urllib.request
>>> local_filename, headers = urllib.request.urlretrieve('https://python.club.tw/')
>>> 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() 可能留下的臨時檔案。

urllib.request 限制

  • 目前,僅支援以下協議:HTTP(0.9 和 1.0 版本)、FTP、本地檔案和資料 URL。

    3.4 版本中已更改: 增加了對資料 URL 的支援。

  • urlretrieve() 的快取功能已被停用,直到有人找到時間正確處理過期時間標頭。

  • 應該有一個函式來查詢某個特定 URL 是否在快取中。

  • 為了向後相容,如果一個 URL 看起來指向一個本地檔案但無法開啟,則會使用 FTP 協議重新解釋該 URL。這有時會導致令人困惑的錯誤訊息。

  • urlopen()urlretrieve() 函式在等待網路連線建立時可能會導致任意長時間的延遲。這意味著在不使用執行緒的情況下,很難使用這些函式構建互動式 Web 客戶端。

  • urlopen()urlretrieve() 返回的資料是伺服器返回的原始資料。這可能是二進位制資料(例如影像)、純文字或(例如)HTML。HTTP 協議在回覆頭中提供型別資訊,可以透過檢視 *Content-Type* 頭來檢查。如果返回的資料是 HTML,您可以使用 html.parser 模組來解析它。

  • 處理 FTP 協議的程式碼無法區分檔案和目錄。這在嘗試讀取指向不可訪問檔案的 URL 時可能導致意外行為。如果 URL 以 / 結尾,則假定它引用目錄並將相應處理。但是,如果嘗試讀取檔案導致 550 錯誤(表示找不到 URL 或無法訪問,通常是由於許可權原因),則路徑將視為目錄,以處理 URL 指定目錄但缺少尾部 / 的情況。當您嘗試獲取因讀取許可權而無法訪問的檔案時,這可能會導致誤導性結果;FTP 程式碼將嘗試讀取它,因 550 錯誤而失敗,然後對不可讀檔案執行目錄列表。如果需要細粒度控制,請考慮使用 ftplib 模組。

urllib.response — urllib 使用的響應類

urllib.response 模組定義了函式和類,它們定義了一個最小的檔案類介面,包括 read()readline()。此模組定義的函式由 urllib.request 模組內部使用。典型的響應物件是 urllib.response.addinfourl 例項。

class urllib.response.addinfourl
url

檢索到的資源的 URL,通常用於確定是否發生了重定向。

headers

EmailMessage 例項的形式返回響應頭。

status

在 3.9 版本中新增。

伺服器返回的狀態碼。

geturl()

從 3.9 版本開始已棄用: 已棄用,轉而使用 url

info()

從 3.9 版本開始已棄用: 已棄用,轉而使用 headers

code

從 3.9 版本開始已棄用: 已棄用,轉而使用 status

getcode()

從 3.9 版本開始已棄用: 已棄用,轉而使用 status