urllib.request
— 用於開啟 URL 的可擴充套件庫¶
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 會使用請求物件中的
fullurl
、data
、headers
、method
引數引發一個 審計事件urllib.Request
。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
(如果檢測到代理設定)、UnknownHandler
、HTTPHandler
、HTTPDefaultErrorHandler
、HTTPRedirectHandler
、FTPHandler
、FileHandler
、HTTPErrorProcessor
。如果 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-Length
或Transfer-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.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_authenticated
和update_authenticated
方法(參見 HTTPPasswordMgrWithPriorAuth 物件),則處理程式將使用給定 URI 的is_authenticated
結果來確定是否隨請求傳送認證憑據。如果is_authenticated
對 URI 返回True
,則傳送憑據。如果is_authenticated
為False
,則不傳送憑據,然後如果收到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.data¶
請求的實體正文,如果未指定則為
None
。3.4 版中已更改: 更改
Request.data
的值現在會刪除之前設定或計算的“Content-Length”頭部。
- Request.method¶
要使用的 HTTP 請求方法。預設情況下,其值為
None
,這意味著get_method()
將正常計算要使用的方法。可以透過在Request
子類中在類級別設定它來提供預設值(從而覆蓋get_method()
中的預設計算),或者透過 *method* 引數將值傳遞給Request
建構函式來設定。在 3.3 版本加入。
3.4 版中已更改: 現在可以在子類中設定預設值;以前只能透過建構函式引數設定。
- Request.get_method()¶
返回一個字串,指示 HTTP 請求方法。如果
Request.method
不是None
,則返回其值,否則如果Request.data
為None
,則返回'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.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:
在每個階段中呼叫這些方法的順序由處理程式例項的排序決定。
每個具有名為
<protocol>_request()
的方法的處理程式都會呼叫該方法來預處理請求。命名為
<protocol>_open()
的處理器被呼叫來處理請求。當處理器返回一個非None
值(即一個響應),或者引發一個異常(通常是URLError
)時,此階段結束。異常允許傳播。實際上,上述演算法首先嚐試名為
default_open()
的方法。如果所有此類方法都返回None
,則演算法將對名為<protocol>_open()
的方法重複執行。如果所有此類方法都返回None
,則演算法將對名為unknown_open()
的方法重複執行。請注意,這些方法的實現可能涉及呼叫父
OpenerDirector
例項的open()
和error()
方法。每個具有名為
<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
呼叫。它應返回一個檔案類物件,如OpenerDirector
的open()
方法的返回值所述,或者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
將使用五個位置引數呼叫此方法一個
Request
物件,一個帶有 HTTP 錯誤正文的檔案類物件,
錯誤的三位數字程式碼,作為字串,
使用者可見的程式碼解釋,作為字串,以及
錯誤頭,作為對映物件。
返回值和引發的異常應與
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)¶
響應重定向返回
Request
或None
。當從伺服器收到重定向時,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 版本中新增。
ProxyHandler 物件¶
- ProxyHandler.<protocol>_open(request)
ProxyHandler
將為建構函式中給定 proxies 字典中具有代理的每個 protocol 提供一個<protocol>_open()
方法。該方法將透過呼叫request.set_proxy()
來修改請求以透過代理,並呼叫鏈中的下一個處理器來實際執行協議。
HTTPPasswordMgr 物件¶
這些方法適用於 HTTPPasswordMgr
和 HTTPPasswordMgrWithDefaultRealm
物件。
- HTTPPasswordMgr.add_password(realm, uri, user, passwd)¶
uri 可以是單個 URI,也可以是 URI 序列。realm、user 和 passwd 必須是字串。這會導致當給定 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)¶
realm、uri、user、passwd 與
HTTPPasswordMgr.add_password()
相同。is_authenticated 設定給定 URI 或 URI 列表的is_authenticated
標誌的初始值。如果 is_authenticated 指定為True
,則忽略 realm。
- HTTPPasswordMgrWithPriorAuth.find_user_password(realm, authuri)¶
- 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 物件¶
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 物件¶
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 物件¶
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 是可以在其中找到物件的本地檔名,headers 是urlopen()
返回的物件(對於遠端物件)的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
例項。