urllib.request --- 用來開啟 URLs 的可擴充函式庫

原始碼:Lib/urllib/request.py


urllib.request module(模組)定義了一些函式與 class(類別)用以開啟 URLs(大部分是 HTTP),並處理各式複雜情況如:basic 驗證與 digest 驗證、重新導向、cookies。

也參考

有關於更高階的 HTTP 用戶端介面,推薦使用 Requests 套件

Availability: not Emscripten, not WASI.

This module does not work or is not available on WebAssembly platforms wasm32-emscripten and wasm32-wasi. See WebAssembly platforms for more information.

urllib.request module 定義下列函式:

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

打開 URL url,其值可以是一個字串或是一個 Request 物件。

data 必須是一個包含傳送給伺服器額外資料的物件,若不需要傳送額外資料則指定為 None。更多細節請見 Request

urllib.request module 使用 HTTP/1.1 並包含 Connection:close header(標頭)在其 HTTP 請求中。

透過選擇性參數 timeout 來指定 blocking operations(阻塞性操作,如:嘗試連接)的 timeout(超時時間),以秒為單位。若沒有指定值,則會使用全域預設超時時間設定。實際上,此參數僅作用於 HTTP、HTTPS 以及 FTP 的連接。

context 有被指定時,它必須是一個 ssl.SSLContext 的實例並描述著各種 SSL 選項。更多細節請見 HTTPSConnection

選擇性參數 cafilecapath 用來指定一組 HTTPS 請求中所需之受信任 CA 憑證。cafile 的值應該指向內容包含一堆 CA 憑證的單一檔案,而 capath 則指向存放一堆雜湊後的憑證檔案的目錄。欲瞭解更多的資訊請參見 ssl.SSLContext.load_verify_locations()

參數 cadefault 已被忽略。

這個函數總是回傳一個可作為 context manager 使用的物件,並有著特性 (property) urlheadersstatus。欲知更多這些特性細節請參見 urllib.response.addinfourl

對於 HTTP 與 HTTPS 的 URLs,這個函式回傳一個稍有不同的 http.client.HTTPResponse 物件。除了上述提到的三個方法外,另有 msg 屬性並有著與 reason 相同的資訊 --- 由伺服器回傳的原因敘述 (reason phrase),而不是在 HTTPResponse 文件中提到的回應 headers。

對於 FTP、檔案、資料的 URLs、以及那些由傳統 classes URLopenerFancyURLopener 所處理的請求,這個函式會回傳一個 urllib.response.addinfourl 物件。

當遇到協定上的錯誤時會引發 URLError

請注意若沒有 handler 處理請求時,None 值將會被回傳。(即使有預設的全域類別 OpenerDirector 使用 UnknownHandler 來確保這種情況不會發生)

另外,若有偵測到代理服務的設定(例如當 *_proxy 環境變數像是:http_proxy 有被設置時),ProxyHandler 會被預設使用以確保請求有透過代理服務來處理。

Python 2.6 或更早版本的遺留函式 urllib.urlopen 已經不再被維護;新函式 urllib.request.urlopen() 對應到舊函式 urllib2.urlopen。有關代理服務的處理,以往是透過傳遞 dictionary(字典)參數給 urllib.urlopen 來取得的,現在則可以透過 ProxyHandler 物件來取得。

觸發一個 auditing event urllib.Request 及其引數 fullurldataheadersmethod

在 3.2 版本變更: 新增 cafilecapath

在 3.2 版本變更: HTTPS 虛擬主機 (virtual hosts) 現已支援,只要 ssl.HAS_SNI 的值為 true。

在 3.2 版本新加入: data 可以是一個可疊代物件。

在 3.3 版本變更: cadefault 被新增。

在 3.4.3 版本變更: context 被新增。

在 3.10 版本變更: context 沒有被指定時,HTTPS 連線現在會傳送一個帶有協定指示器 http/1.1 的 ALPN 擴充 (extension)。自訂的 context 應該利用 set_alpn_protocol() 來自行設定 ALPN 協定。

在 3.6 版本開始棄用: cafilecapathcadefault 已經被棄用並應改為使用 context。請改用 ssl.SSLContext.load_cert_chain(),或是讓 ssl.create_default_context() 選取系統中受信任的 CA 憑證。

urllib.request.install_opener(opener)

安裝一個 OpenerDirector 實例作為預設的全域 opener。僅在當你想要讓 urlopen 使用該 opener 時安裝一個 opener,否則的話應直接呼叫 OpenerDirector.open() 而非 urlopen()。程式碼不會檢查 class 是否真的為 OpenerDirector,而是任何具有正確介面的 class 都能適用。

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

回傳一個 OpenerDirector 實例,以給定的順序把 handlers 串接起來。handlers 可以是 BaseHandler 的實例,亦或是 BaseHandler 的 subclasses(這個情況下必須有不帶參數的建構函式能夠被呼叫)。以下 classes 的實例順位會在 handlers 之前,除非 handlers 已經包含它們,是它們的實例,或是它們的 subclasses:ProxyHandler(如果代理服務設定被偵測到)、UnknownHandlerHTTPHandlerHTTPDefaultErrorHandlerHTTPRedirectHandlerFTPHandlerFileHandlerHTTPErrorProcessor

如果 Python 安裝時已帶有 SSL 支援(如果 ssl module 能夠被 import),則 HTTPSHandler 也在上述 class 之中。

一個 BaseHandler 的 subclass 可能透過改變其 handler_order 屬性來調整它在 handlers list 中的位置。

urllib.request.pathname2url(path)

將路徑名 path 從路徑的本地語法 (local syntax) 轉換為 URL 中的 path component(路徑元件)格式。本函式並不會產生完整的 URL。回傳值將使用 quote() 函式先進行編碼過。

urllib.request.url2pathname(path)

將一個用 "%" 編碼過的 URL path component path 轉換為路徑的本地語法 (local syntax)。本函式並不接受完整的 URL。本函式使用 unquote() 來將 path 解碼。

urllib.request.getproxies()

這個輔助函式 (helper function) 回傳一個代理伺服器 URL mappings(對映)的 dictionary。在所有的作業系統中,它首先掃描環境中有著 <scheme>_proxy 名稱的變數(忽略大小寫的),如果找不到的話就會在 macOS 中的系統設定 (System Configuration) 或是 Windows 系統中的 Windows Systems Registry 尋找代理服務設定。如果大小寫的環境變數同時存在且值有不同,小寫的環境變數會被選用。

備註

如果環境變數 REQUEST_METHOD 有被設置(通常這代表著你的 script 是運行在一個共用閘道介面 (CGI) 環境中),那麼環境變數 HTTP_PROXY (大寫的 _PROXY)將被忽略。這是因為變數可以透過使用 "Proxy:" HTTP header 被注入。如果需要在共用閘道介面環境中使用 HTTP 代理服務,可以明確使用 ProxyHandler,亦或是確認變數名稱是小寫的(或至少 _proxy 後綴是小寫的)。

提供了以下的 classes:

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

這個 class 是一個 URL 請求的抽象 class。

url 是一個包含有效 URL 的字串。

data 必須是一個包含要送到伺服器的附加資料的物件,若不需帶附加資料則其值應為 None。目前 HTTP 請求是唯一有使用 data 參數的,其支援的物件型別包含位元組、類檔案物件 (file-like objects)、以及可疊代的類位元組串物件 (bytes-like objects)。如果沒有提供 Content-LengthTransfer-Encoding headers 欄位,HTTPHandler 將會根據 data 的型別設置這些 header。Content-Length 會被用來傳送位元組串物件,而 RFC 7230 章節 3.3.1 所定義的 Transfer-Encoding: chunked 則會被用來傳送檔案或是其它可疊代物件 (iterables)。

對於一個 HTTP POST 請求方法,data 應為一個標準 application/x-www-form-urlencoded 格式的 buffer。urllib.parse.urlencode() 方法接受一個 mapping 或是 sequence(序列)的 2-tuples,並回傳一個對應格式的 ASCII 字串。在被作為 data 參數前它應該被編碼成位元組串。

headers 必須是一個 dictionary,並會被視為如同每對 key 和 value 作為引數來呼叫 add_header()。經常用於「偽裝」 User-Agent header 的值,這個 header 是用來讓一個瀏覽器向伺服器表明自己的身分 --- 有些 HTTP 伺服器僅允許來自普通瀏覽器的請求,而不接受來自程式腳本的請求。例如,Mozilla Firefox 會將 header 的值設為 "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11",而 urllib 的值則是 "Python-urllib/2.6"(在 Python 2.6 上)。所有 header 的鍵都會以 camel case(駝峰式大小寫)來傳送。

當有給定 data 引數時,一個適當的 Content-Type header 應該被設置。如果這個 header 沒有被提供且 data 也不為 None 時,預設值 Content-Type: application/x-www-form-urlencoded 會被新增至請求中。

接下來的兩個引數的介紹提供給那些有興趣正確處理第三方 HTTP cookies 的使用者:

origin_req_host 應為原始傳輸互動的請求主機 (request-host),如同在 RFC 2965 中的定義。預設值為 http.cookiejar.request_host(self)。這是使用者發起的原始請求的主機名稱或是 IP 位址。例如當請求是要求一個 HTML 文件中的一個影像,則這個屬性應為請求包含影像頁面的請求主機。

unverifiable 應該標示一個請求是否是無法驗證的,如同在 RFC 2965 中的定義。其預設值為 False。一個無法驗證的請求是指使用者沒有機會去批准請求的 URL,例如一個對於 HTML 文件中的影像所做的請求,而使用者沒有機會去批准是否能自動擷取影像,則這個值應該為 true。

method 應為一個標示 HTTP 請求方法的字串(例如:'HEAD')。如果有提供值,則會被存在 method 屬性中且被 get_method() 所使用。當 dataNone 時,其預設值為 'GET',否則預設值為 'POST'。Subclasses 可以透過設置其 method 屬性來設定不一樣的預設請求方法。

備註

如果資料物件無法重複提供其內容(例如一個檔案或是只能產生一次內容的可疊代物件)且請求因為 HTTP 重導向 (redirects) 或是 HTTP 驗證 (authentication) 而被重新嘗試傳送,則該請求不會正常運作。data 會接在 headers 之後被送至 HTTP 伺服器。此函式庫沒有支援 100-continue expectation。

在 3.3 版本變更: 新增 Request.method 引數到 Request class。

在 3.4 版本變更: 能夠在 class 中設置預設的 Request.method

在 3.6 版本變更: 如果 Content-Length 尚未被提供且 data 既不是 None 也不是一個位元組串物件,則不會觸發錯誤,並 fall back(後備)使用分塊傳輸編碼 (chunked transfer encoding)。

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 Settings 部分获取,而在 macOS 环境下代理信息会从 System Configuration Framework 获取。

若要禁用自动检测出来的代理,请传入空的字典对象。

环境变量 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 URL。

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 属性将会返回附带片段(fragment)的初始请求 URL。

Request.type

URI 方式。

Request.host

URI 权限,通常是整个主机,但也有可能带有冒号分隔的端口号。

Request.origin_req_host

请求的原始主机,不含端口。

Request.selector

URI 路径。若 Request 使用代理,selector 将会是传给代理的完整 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 不为 None ,则返回其值。否则若 Request.data 为 则返回 'GET',不为 None 则返回 'POST' 。只对 HTTP 请求有效。

在 3.3 版本變更: 现在 get_method 会兼顾 Request.method 的值。

Request.add_header(key, val)

向请求添加一个标头。 标头目前会被所有处理句柄忽略但只有 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)

连接代理服务器,为当前请求做准备。 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() — 表明该 handler 知道如何打开 protocol 协议的URL。

    更多資訊請見 BaseHandler.<protocol>_open()

  • http_error_<type>() — 表明该 handler 知道如何处理代码为 type 的 HTTP 错误。

    更多資訊請見 BaseHandler.http_error_<nnn>()

  • <protocol>_error() — 表明该 handler 知道如何处理来自协议为 protocol (非http)的错误。

  • <protocol>_request() — 表明该 handler 知道如何预处理协议为 protocol 的请求。

    更多資訊請見 BaseHandler.<protocol>_request()

  • <protocol>_response() — 表明该 handler 知道如何后处理协议为 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 响应码来确定具体的错误处理程序;请参考 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 加为父 OpenerDirector。

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)

The same as http_error_301(), but called for the 'temporary redirect' response. It does not allow changing the request method from POST to GET.

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

The same as http_error_301(), but called for the 'permanent redirect' response. It does not allow changing the request method from POST to GET.

在 3.11 版本新加入.

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

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 应该是请求中包含 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() 方法相同。

例子

如何使用 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。

This example replaces the default ProxyHandler with one that uses programmatically supplied proxy URLs, and adds proxy authorization support with 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() 函数在等待网络连接建立时会导致任意长时间的延迟。 这意味着在不使用线程的情况下搭建一个可交互的 Web 客户端是非常困难的。

  • urlopen()urlretrieve() 返回的数据就是服务器所返回的原始数据。 这可以是二进制数据(如图片)、纯文本或 HTML 代码等。 HTTP 协议在响应标头中提供了类型信息,这可以通过读取 Content-Type 标头来查看。 如果返回的数据是 HTML,你可以使用 html.parser 模块来解析它。

  • 处理 FTP 协议的代码无法区分文件和目录。 这在尝试读取指向不可访问的 URL 时可能导致意外的行为。 如果 URL 以一个 / 结束,它会被认为指向一个目录并将作相应的处理。 但是如果读取一个文件的尝试导致了 550 错误(表示 URL 无法找到或不可访问,这常常是由于权限原因),则该路径会被视为一个目录以便处理 URL 是指定一个目录但略去了末尾 / 的情况。 这在你尝试获取一个因其设置了读取权限因而无法访问的文件时会造成误导性的结果;FTP 代码将尝试读取它,因 550 错误而失败,然后又为这个不可读取的文件执行目录列表操作。 如果需要细粒度的控制,请考虑使用 ftplib 模块,子类化 FancyURLopener,或是修改 _urlopener 来满足你的需求。

urllib.response --- urllib 使用的 Response 类

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

getstatus()

在 3.9 版本開始棄用: 已弃用,建议改用 status