urllib.request — 用于打开 URL 的可扩展库

源代码: Lib/urllib/request.py


urllib.request 模块定义了一些函数和类,用于在复杂环境(基本和摘要式身份验证、重定向、Cookie 等)中打开 URL(主要是 HTTP)。

另请参阅

建议使用 Requests 包 作为更高级别的 HTTP 客户端接口。

警告

在 macOS 上,在使用 os.fork() 的程序中使用此模块是不安全的,因为 macOS 的 getproxies() 实现使用了更高级别的系统 API。将环境变量 no_proxy 设置为 * 以避免此问题(例如 os.environ["no_proxy"] = "*")。

可用性:不可用于 Emscripten,不可用于 WASI。

此模块在 WebAssembly 平台 wasm32-emscriptenwasm32-wasi 上不可用或无法工作。有关更多信息,请参阅 WebAssembly 平台

urllib.request 模块定义了以下函数

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, 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

可选的 cafilecapath 参数为 HTTPS 请求指定一组受信任的 CA 证书。cafile 应指向包含 CA 证书包的单个文件,而 capath 应指向散列证书文件目录。更多信息可以在 ssl.SSLContext.load_verify_locations() 中找到。

cadefault 参数被忽略。

此函数始终返回一个可以作为 上下文管理器 工作的对象,并具有属性 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。代理处理,以前是通过向 urllib.urlopen 传递字典参数来完成的,现在可以通过使用 ProxyHandler 对象来实现。

默认的 opener 会使用从请求对象中获取的参数 fullurldataheadersmethod 引发一个 审计事件 urllib.Request

在 3.2 版更改: 添加了 cafilecapath

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

data 可以是一个可迭代对象。

在 3.3 版更改: 添加了 cadefault

在 3.4.3 版更改: 添加了 context

在 3.10 版更改: 当没有给出 context 时,HTTPS 连接现在会发送一个带有协议指示符 http/1.1 的 ALPN 扩展。自定义 context 应该使用 set_alpn_protocols() 设置 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()。代码不会检查是否为真正的 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)

将路径名 path 从本地路径语法转换为 URL 路径组件中使用的形式。这不会生成完整的 URL。返回值将使用 quote() 函数进行引用。

urllib.request.url2pathname(path)

将路径组件 path 从百分比编码的 URL 转换为本地路径语法。这不接受完整的 URL。此函数使用 unquote() 解码 path

urllib.request.getproxies()

此辅助函数返回一个字典,其中包含方案到代理服务器 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 将用于发送字节对象,而 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() 使用。如果 dataNone,则默认为 'GET',否则为 'POST'。子类可以通过在类本身中设置 method 属性来指示不同的默认方法。

注意

如果数据对象无法多次传递其内容(例如,只能生成一次内容的文件或可迭代对象),并且针对 HTTP 重定向或身份验证重试了请求,则请求将无法按预期工作。数据会在标头之后立即发送到 HTTP 服务器。库中不支持 100-continue 预期。

版本 3.3 中的变化: 在 Request 类中添加了 Request.method 参数。

版本 3.4 中的变化: 默认的 Request.method 可以在类级别指示。

版本 3.6 中的变化: 如果没有提供 Content-Length 并且 data 既不是 None 也不是字节对象,则不会引发错误。改为回退使用分块传输编码。

class urllib.request.OpenerDirector

OpenerDirector 类通过链接在一起的 BaseHandler 打开 URL。它管理处理程序的链接以及从错误中恢复。

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

维护一个 (领域, URI) -> (用户名, 密码) 映射的数据库。

class urllib.request.HTTPPasswordMgrWithDefaultRealm

维护一个 (领域, URI) -> (用户名, 密码) 映射的数据库。领域 None 被视为一个通配符领域,如果没有其他领域匹配,则会搜索该领域。

class urllib.request.HTTPPasswordMgrWithPriorAuth

HTTPPasswordMgrWithDefaultRealm 的一个变体,它还有一个 URI -> 是否已认证 映射的数据库。基本身份验证处理程序可以使用它来确定何时立即发送身份验证凭据,而不是先等待 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 子类中设置类级别的默认值,或者通过 method 参数将值传递给 Request 构造函数,来设置其值(从而覆盖 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 将替换实例的 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 将调用它。它应该返回一个类似文件的对象,如 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 自动调用,并且通常不应在其他情况下调用。

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 的重定向。否则,如果其他处理程序不应该尝试处理此 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.<protocol>_open(request)

对于在构造函数中给出的 *proxies* 字典中具有代理的每个 *protocol*,ProxyHandler 将具有一个方法 <protocol>_open()。该方法将通过调用 request.set_proxy() 修改请求以通过代理,并调用链中的下一个处理程序来实际执行协议。

HTTPPasswordMgr 对象

这些方法在 HTTPPasswordMgrHTTPPasswordMgrWithDefaultRealm 对象上可用。

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)

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://www.pythonlang.cn/")。在任何一种情况下,授权机构都不能包含用户信息组件(因此,"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* 应该是包含域信息的请求头的名称,*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 错误代码,立即返回响应对象。

对于非 200 错误代码,这只是通过 OpenerDirector.error() 将作业传递给 http_error_<type>() 处理程序方法。最终,如果没有其他处理程序处理错误,HTTPDefaultErrorHandler 将引发 HTTPError

HTTPErrorProcessor.https_response(request, response)

处理 HTTPS 错误响应。

行为与 http_response() 相同。

示例

除了以下示例之外,HOWTO 使用 urllib 包获取互联网资源 中还提供了更多示例。

此示例获取 python.org 主页并显示其前 300 个字节。

>>> import urllib.request
>>> with urllib.request.urlopen('https://www.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://www.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://www.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://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() 默认提供许多处理程序,包括 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://www.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 会自动向每个 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 的 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://www.pythonlang.cn") as f:
...     f.read().decode('utf-8')
...

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

>>> import urllib.request
>>> opener = urllib.request.FancyURLopener({})
>>> with opener.open("https://www.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, headers),其中 filename 是可以在其中找到该对象的本地文件名,headersurlopen() 返回的对象的 info() 方法返回的内容(对于远程对象)。异常与 urlopen() 相同。

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

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

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

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

收集在 x509 中的其他关键字参数可用于在使用 https: 方案时对客户端进行身份验证。支持关键字 key_filecert_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