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 选项的 ssl.SSLContext 实例。 有关详细信息,请参阅 HTTPSConnection

此函数始终返回一个可以作为 上下文管理器 并且具有属性 urlheadersstatus 的对象。 有关这些属性的更多详细信息,请参阅 urllib.response.addinfourl

对于 HTTP 和 HTTPS URL,此函数返回一个经过稍微修改的 http.client.HTTPResponse 对象。 除了上面的三个新方法之外,msg 属性包含与 reason 属性相同的信息 — 服务器返回的原因短语 — 而不是 HTTPResponse 文档中指定的响应头。

对于 FTP、文件和数据 URL 以及由旧版 URLopenerFancyURLopener 类显式处理的请求,此函数返回一个 urllib.response.addinfourl 对象。

在协议错误时引发 URLError

请注意,如果没有处理请求的处理程序,则可能会返回 None (尽管默认安装的全局 OpenerDirector 使用 UnknownHandler 来确保这种情况永远不会发生)。

此外,如果检测到代理设置(例如,当设置了 *_proxy 环境变量(如 http_proxy)时),则默认安装 ProxyHandler 并确保请求通过代理处理。

来自 Python 2.6 及更早版本的旧版 urllib.urlopen 函数已停用; urllib.request.urlopen() 对应于旧的 urllib2.urlopen。 可以通过使用 ProxyHandler 对象来获得以前通过将字典参数传递给 urllib.urlopen 来完成的代理处理。

默认的 opener 引发一个 审计事件 urllib.Request,其参数 fullurldataheadersmethod 取自请求对象。

在 3.2 版本中更改: 添加了 cafilecapath

如果可能(即如果 ssl.HAS_SNI 为 true),现在支持 HTTPS 虚拟主机。

data 可以是可迭代的对象。

在 3.3 版本中更改: 添加了 cadefault

在 3.4.3 版本中更改: 添加了 context

在 3.10 版本中变更: 当没有提供context时,HTTPS 连接现在会发送一个带有协议指示符 http/1.1 的 ALPN 扩展。自定义的 context 应该使用 set_alpn_protocols() 设置 ALPN 协议。

在 3.13 版本中变更: 移除 cafilecapathcadefault 参数:请改用 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 包含以下类的实例、它们的子类或实例:ProxyHandler(如果检测到代理设置)、UnknownHandlerHTTPHandlerHTTPDefaultErrorHandlerHTTPRedirectHandlerFTPHandlerFileHandlerHTTPErrorProcessor,否则这些类的实例将在 handler 之前。

如果 Python 安装支持 SSL(即,如果可以导入 ssl 模块),也会添加 HTTPSHandler

BaseHandler 的子类也可以更改其 handler_order 属性,以修改其在处理程序列表中的位置。

urllib.request.pathname2url(path)

将给定的本地路径转换为 file: URL。此函数使用 quote() 函数对路径进行编码。出于历史原因,返回值省略了 file: 方案前缀。此示例展示了如何在 Windows 上使用该函数

>>> from urllib.request import pathname2url
>>> path = 'C:\\Program Files'
>>> 'file:' + pathname2url(path)
'file:///C:/Program%20Files'
urllib.request.url2pathname(url)

将给定的 file: URL 转换为本地路径。此函数使用 unquote() 来解码 URL。出于历史原因,给定的值必须省略 file: 方案前缀。此示例展示了如何在 Windows 上使用该函数

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

此帮助函数返回一个从 scheme 到代理服务器 URL 映射的字典。它首先扫描所有操作系统的环境中名为 <scheme>_proxy 的变量(不区分大小写),如果找不到,则从 macOS 的系统配置和 Windows 的 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 将用于发送字节对象,而 RFC 7230 第 3.3.1 节中指定的 Transfer-Encoding: chunked 将用于发送文件和其他可迭代对象。

对于 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() 方法使用。如果 dataNone,则默认值为 '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 的 realm 被视为捕获所有 realm,如果没有其他 realm 匹配,则搜索该 realm。

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 对象 部分。

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 的类。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.full_url

传递给构造函数的原始 URL。

在 3.4 版本中更改。

Request.full_url 是一个具有设置器、获取器和删除器的属性。获取 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 子类中在类级别设置默认值,或者通过在 Request 构造函数中通过 method 参数传递值来设置其值(从而覆盖 get_method() 中的默认计算)。

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)

通过连接到代理服务器来准备请求。hosttype 将替换实例中的值,并且实例的选择器将是构造函数中给定的原始 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() — 表示处理程序知道如何处理来自(非 httpprotocol 的错误。

  • <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 将调用它。它应返回一个类似文件的对象,如 open() 方法的返回值中所述 OpenerDirector,或者 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 自动调用,并且通常不应在其他情况下调用。

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.<协议>_request(req)

此方法没有BaseHandler 中定义,但是如果子类想要预处理给定协议的请求,则应该定义它。

如果定义了此方法,则父级 OpenerDirector 将会调用它。req 将是一个 Request 对象。返回值应该是一个 Request 对象。

BaseHandler.<协议>_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 的重定向。否则,如果没有其他处理程序应尝试处理此 URL,则引发 HTTPError,如果您无法处理但其他处理程序可能会处理,则返回 None

注意

此方法的默认实现并不严格遵循 RFC 2616,该规范规定,未经用户确认,不得自动重定向对 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.<协议>_open(request)

对于构造函数中给定的 proxies 字典中具有代理的每个协议ProxyHandler 都将有一个方法 <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)

获取给定 realm 和 URI 的用户/密码(如果有)。如果没有匹配的用户/密码,此方法将返回 (None, None)

对于 HTTPPasswordMgrWithDefaultRealm 对象,如果给定的 realm 没有匹配的用户/密码,则会搜索 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 应该是标头的名称,该标头中包含有关请求中 realm 的信息,host 指定要进行身份验证的 URL 和路径,req 应该是(失败的)Request 对象,而 headers 应该是错误标头。

host 是授权机构(例如,"python.org")或包含授权机构组件的 URL(例如,"https://pythonlang.cn/")。在任何一种情况下,授权机构都不得包含 userinfo 组件(因此,"python.org""python.org:80" 没问题,"joe:[email protected]" 则不行)。

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 请求,它可以是 GET 或 POST,具体取决于 req.has_data()

HTTPSHandler 对象

HTTPSHandler.https_open(req)

发送一个 HTTPS 请求,它可以是 GET 或 POST,具体取决于 req.has_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 错误代码,立即返回 response 对象。

对于非 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://pythonlang.cn/') 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 网站使用其元标记中指定的 utf-8 编码,我们将使用相同的编码来解码字节对象。

>>> with urllib.request.urlopen('https://pythonlang.cn/') 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

也可以在不使用 上下文管理器 方法的情况下实现相同的结果。

>>> import urllib.request
>>> f = urllib.request.urlopen('https://pythonlang.cn/')
>>> 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://127.0.0.1/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://127.0.0.1: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() 默认情况下提供许多处理程序,包括 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:
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', 'https://pythonlang.cn/')
# Customize the default User-Agent header value:
req.add_header('User-Agent', 'urllib-example/0.1 (Contact: . . .)')
r = urllib.request.urlopen(req)

OpenerDirector 自动将 User-Agent 标头添加到每个 Request。要更改此行为,请执行以下操作

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 的 params 输出在作为数据发送到 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("https://pythonlang.cn") as f:
...     f.read().decode('utf-8')
...

以下示例根本不使用代理,覆盖环境设置

>>> import urllib.request
>>> opener = urllib.request.FancyURLopener({})
>>> with opener.open("https://pythonlang.cn/") as f:
...     f.read().decode('utf-8')
...

旧接口

以下函数和类是从 Python 2 模块 urllib(而不是 urllib2)移植过来的。它们可能在未来的某个时候被弃用。

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

将 URL 表示的网络对象复制到本地文件。如果 URL 指向本地文件,除非提供了 filename,否则不会复制该对象。返回一个元组 (filename, headers),其中 *filename* 是可以找到该对象的本地文件名,而 *headers* 是 urlopen() 返回的对象(对于远程对象)的 info() 方法返回的内容。异常与 urlopen() 相同。

第二个参数(如果存在)指定要复制到的文件位置(如果不存在,则该位置将是具有生成名称的临时文件)。第三个参数(如果存在)是一个可调用对象,它将在建立网络连接时调用一次,然后在每次读取块后调用一次。该可调用对象将被传递三个参数:到目前为止传输的块计数、以字节为单位的块大小以及文件的总大小。在较旧的 FTP 服务器上,第三个参数可能是 -1,这些服务器不返回检索请求的文件大小。

以下示例说明了最常见的用法场景

>>> import urllib.request
>>> local_filename, headers = urllib.request.urlretrieve('https://pythonlang.cn/')
>>> 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 类发送一个 User-Agent 标头,其值为 urllib/VVV,其中 *VVV* 是 urllib 版本号。应用程序可以通过子类化 URLopenerFancyURLopener,并在子类定义中将类属性 version 设置为适当的字符串值来定义自己的 User-Agent 标头。

可选的 *proxies* 参数应该是一个字典,将方案名称映射到代理 URL,其中空字典会完全关闭代理。其默认值为 None,在这种情况下,如果存在环境代理设置,将使用该设置,如上面 urlopen() 的定义中所讨论的那样。

当使用 https: 方案时,收集在 *x509* 中的其他关键字参数可用于客户端的身份验证。支持关键字 *key_file* 和 *cert_file* 以提供 SSL 密钥和证书;两者都需要支持客户端身份验证。

如果服务器返回错误代码,URLopener 对象将引发 OSError 异常。

open(fullurl, data=None)

使用适当的协议打开 *fullurl*。此方法设置缓存和代理信息,然后使用其输入参数调用适当的 open 方法。如果方案无法识别,则调用 open_unknown()。*data* 参数的含义与 urlopen() 的 *data* 参数相同。

此方法始终使用 quote() 对 *fullurl* 进行引用。

open_unknown(fullurl, data=None)

可重写的接口,用于打开未知的 URL 类型。

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

检索 *url* 的内容并将其放置在 *filename* 中。返回值是一个元组,其中包含本地文件名和一个包含响应标头的 email.message.Message 对象(对于远程 URL)或 None (对于本地 URL)。然后,调用者必须打开并读取 *filename* 的内容。如果未给出 *filename* 并且 URL 指的是本地文件,则返回输入文件名。如果 URL 是非本地的并且未给出 *filename*,则文件名是 tempfile.mktemp() 的输出,其后缀与输入 URL 的最后一个路径组件的后缀匹配。如果给出了 *reporthook*,则它必须是一个接受三个数字参数的函数:块号、读取块的最大大小以及下载的总大小(如果未知则为 -1)。它将在启动时调用一次,并在每次从网络读取数据块后调用一次。对于本地 URL,*reporthook* 将被忽略。

如果 *url* 使用 http: 方案标识符,则可以提供可选的 *data* 参数来指定 POST 请求(通常请求类型为 GET)。*data* 参数必须采用标准 application/x-www-form-urlencoded 格式;请参阅 urllib.parse.urlencode() 函数。

version

变量,用于指定 opener 对象的用户代理。要使 urllib 告诉服务器它是一个特定的用户代理,请在子类中将其设置为类变量,或在调用基构造函数之前将其设置为构造函数。

class urllib.request.FancyURLopener(...)

自版本 3.3 起弃用。

FancyURLopenerURLopener 的子类,为以下 HTTP 响应代码提供默认处理:301、302、303、307 和 401。对于上面列出的 30x 响应代码,使用 Location 标头来获取实际的 URL。对于 401 响应代码(需要身份验证),将执行基本 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 看起来指向本地文件但该文件无法打开,则会使用 FTP 协议重新解释该 URL。这有时会导致令人困惑的错误消息。

  • 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 使用的响应类

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