Skip to main content

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

源代码: Lib/urllib/request.py


urllib.request 模块定义了在复杂世界中帮助打开URL(主要是HTTP)的函数和类 - 基本和摘要认证,重定向,cookie等。

参见

建议将 请求包 用于更高级别的HTTP客户端接口。

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 参数被忽略。

这个函数总是返回一个对象,它可以作为一个 context manager,并有方法如

  • geturl() —返回检索到的资源的URL,通常用于确定是否遵循重定向

  • info() —以 email.message_from_string() 实例的形式返回页面的元信息,例如头部(见 快速参考HTTP头

  • getcode() - 返回响应的HTTP状态代码。

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

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

提出 URLError 协议错误。

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

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

Python 2.6和更早版本的传统 urllib.urlopen 函数已停止; urllib.request.urlopen() 对应于旧的 urllib2.urlopen。代理处理,通过传递字典参数到 urllib.urlopen,可以通过使用 ProxyHandler 对象获得。

在 3.2 版更改: cafilecapath

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

3.2 新版功能: data 可以是一个可迭代的对象。

在 3.3 版更改: 加入 cadefault

在 3.4.3 版更改: 加入 context

3.6 版后已移除: cafilecapathcadefault 不赞成使用 context。请使用 ssl.SSLContext.load_cert_chain(),或者让 ssl.create_default_context() 为您选择系统的受信任的CA证书。

urllib.request.install_opener(opener)

安装 OpenerDirector 实例作为默认全局启动器。安装开瓶器只有当你想要urlopen使用开瓶器;否则,简单地调用 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转换为路径的本地语法。这不接受完整的网址。此功能使用 unquote() 来解码 path

urllib.request.getproxies()

这个帮助函数返回一个方案到代理服务器URL映射的字典。它首先针对所有操作系统,以不区分大小写的方式扫描名为 <scheme>_proxy 的变量,并在找不到它时,从Mac OSX系统配置(Mac OS X和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 应为包含有效网址的字符串。

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 不是无,则将默认添加 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。无法验证的请求是用户的网址无法验证的请求。例如,如果请求是针对HTML文档中的图像,并且用户没有批准自动提取图像的选项,则应该是真的。

method 应为指示将使用的HTTP请求方法(例如,'HEAD')的字符串。如果提供,其值将存储在 method 属性中,并由 get_method() 使用。如果 dataNone'POST',则默认值为 'GET'。子类可以通过在类本身中设置 method 属性来指示不同的默认方法。

注解

如果数据对象无法多次传递其内容(例如,只能生成一次内容的文件或可迭代器),则请求将无法正常工作,并且会对HTTP重定向或身份验证重试请求。 data 在头部之后立即发送到HTTP服务器。在图书馆里没有支持100继续的期望。

在 3.3 版更改: Request.method 参数被添加到Request类。

在 3.4 版更改: 可以在类级别指示默认 Request.method

在 3.6 版更改: 如果未提供 Content-Lengthdata 既不是 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设置”部分获取代理设置,在Mac OS X环境中,将从OS X系统配置框架检索代理信息。

禁用自动检测代理传递一个空字典。

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)

这是一个mixin类,帮助HTTP认证,无论是对远程主机还是代理。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西;有关必须支持的接口的信息,请参阅 H asswordMgr对象 部分。如果 passwd_mgr 还提供 is_authenticatedupdate_authenticated 方法(参见 H asswordMgrWithPriorAuth对象),则处理程序将使用给定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 兼容的东西;有关必须支持的接口的信息,请参阅 H asswordMgr对象 部分。当出现错误的认证方案时,HTTPBasicAuthHandler将产生 ValueError

class urllib.request.ProxyBasicAuthHandler(password_mgr=None)

处理与代理的身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西;有关必须支持的接口的信息,请参阅 H asswordMgr对象 部分。

class urllib.request.AbstractDigestAuthHandler(password_mgr=None)

这是一个mixin类,帮助HTTP认证,无论是对远程主机还是代理。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西;有关必须支持的接口的信息,请参阅 H asswordMgr对象 部分。

class urllib.request.HTTPDigestAuthHandler(password_mgr=None)

处理与远程主机的身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西;有关必须支持的接口的信息,请参阅 H asswordMgr对象 部分。当同时添加摘要认证处理程序和基本认证处理程序时,总是首先尝试摘要认证。如果摘要认证再次返回40x响应,则将其发送到处理的基本认证处理器。当呈现了除Digest或Basic之外的认证方案时,该Handler方法将产生 ValueError

在 3.3 版更改: 在不支持的身份验证方案上升级 ValueError

class urllib.request.ProxyDigestAuthHandler(password_mgr=None)

处理与代理的身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西;有关必须支持的接口的信息,请参阅 H asswordMgr对象 部分。

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

打开数据网址。

3.4 新版功能.

class urllib.request.FTPHandler

打开FTP URL。

class urllib.request.CacheFTPHandler

打开FTP URL,保持打开的FTP连接缓存以最小化延迟。

class urllib.request.UnknownHandler

用于处理未知网址的全部类。

class urllib.request.HTTPErrorProcessor

处理HTTP错误响应。

21.6.1. 请求对象

以下方法描述了 Request 的公共接口,因此所有的都可以在子类中被覆盖。它还定义了几个公共属性,客户端可以使用这些属性来检查解析的请求。

Request.full_url

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

在 3.4 版更改.

Request.full_url是一个具有setter,getter和deleter的属性。获取 full_url 将返回包含片段的原始请求URL(如果存在)。

Request.type

URI方案。

Request.host

URI权限,通常为主机,但也可以包含由冒号分隔的端口。

Request.origin_req_host

原始主机的请求,没有端口。

Request.selector

URI路径。如果 Request 使用代理,则选择器将是传递给代理的完整URL。

Request.data

请求的实体主体,如果未指定,则为 None

在 3.4 版更改: 更改 Request.data 的值现在删除“Content-Length”报头(如果之前已设置或计算)。

Request.unverifiable

boolean,指示请求是否是RFC 2965定义的不可验证的。

Request.method

要使用的HTTP请求方法。默认情况下,其值为 None,这意味着 get_method() 将对要使用的方法执行其正常计算。它的值可以被设置(从而覆盖 get_method() 中的默认计算),通过在 Request 子类中的类级别设置一个默认值,或者通过 method 参数传递一个值到 Request 构造函数。

3.3 新版功能.

在 3.4 版更改: 现在可以在子类中设置默认值;以前它只能通过constructor参数设置。

Request.get_method()

返回一个表示HTTP请求方法的字符串。如果 Request.method 不是 None,返回其值,否则如果 Request.dataNone,则返回 'GET',否则返回 '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)

返回实例是否具有指定的header_checks常量和无向)。

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 版更改: 请求方法add_data,has_data,get_data,get_type,get_host,get_selector,get_origin_req_host和is_unverifiable,因为3.3已被删除而被弃用。

21.6.2. OpenerDirector对象

OpenerDirector 实例有以下方法:

OpenerDirector.add_handler(handler)

handler 应该是 BaseHandler 的一个实例。将搜索以下方法,并将其添加到可能的链中(请注意,HTTP错误是一种特殊情况)。

  • protocol_open() —表示处理程序知道如何打开 protocol URL。

  • http_error_type() —表示处理程序知道如何使用HTTP错误代码 type 处理HTTP错误。

  • protocol_error() —表示处理程序知道如何处理来自(非httpprotocol 的错误。

  • protocol_request() —表示处理程序知道如何预处理 protocol 请求。

  • protocol_response() —表示处理器知道如何后处理 protocol 响应的信号。

OpenerDirector.open(url, data=None[, timeout])

打开给定的 url (可以是请求对象或字符串),可选地传递给定的 data。引用的参数,返回值和异常与 urlopen() (它只是在当前安装的全局 OpenerDirector 上调用 open() 方法)的参数,返回值和异常相同。可选的 timeout 参数指定阻塞操作(如连接尝试)的超时(以秒为单位)(如果未指定,将使用全局默认超时设置)。超时功能实际上只适用于HTTP,HTTPS和FTP连接)。

OpenerDirector.error(proto, *args)

处理给定协议的错误。这将调用具有给定参数(其是协议特定的)的给定协议的注册的错误处理程序。 HTTP协议是一种特殊情况,它使用HTTP响应代码来确定特定的错误处理程序;请参阅处理程序类的 http_error_*() 方法。

返回值和异常与 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() 的方法的处理程序都有调用该方法来后处理响应。

21.6.3. BaseHandler对象

BaseHandler 对象提供了几个直接有用的方法,以及其他一些意在被派生类使用的方法。这些是直接使用:

BaseHandler.add_parent(director)

添加导演为父级。

BaseHandler.close()

删除任何父母。

以下属性和方法只应由从 BaseHandler 派生的类使用。

注解

已经采用该惯例,将定义 protocol_request()protocol_response() 方法的子类命名为 *Processor;所有其他都命名为 *Handler

BaseHandler.parent

有效的 OpenerDirector,可用于使用不同的协议打开或处理错误。

BaseHandler.default_open(req)

这个方法是在 BaseHandler 中定义的 not,但是子类应该定义它,如果他们想捕获所有的URL。

此方法(如果实现)将由父 OpenerDirector 调用。它应该返回一个像 OpenerDirectorNoneopen() 的返回值中描述的类文件对象。它应该提高 URLError,除非一个真正的异常事情发生(例如,MemoryError 不应映射到 URLError)。

此方法将在任何协议特定的打开方法之前调用。

BaseHandler.protocol_open(req)

这个方法是在 BaseHandler 中定义的 not,但是子类应该定义它,如果他们想使用给定的协议处理URL。

此方法(如果已定义)将由父 OpenerDirector 调用。返回值应与 default_open() 相同。

BaseHandler.unknown_open(req)

这个方法是在 BaseHandler 中定义的 not,但是子类应该定义它,如果他们想捕获没有特定注册的处理程序打开它的所有URL。

这个方法,如果实现,将由 parent OpenerDirector 调用。返回值应与 default_open() 相同。

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

此方法是在 BaseHandler 中定义的 not,但是子类应该覆盖它,如果他们打算提供一个catch-all为未处理的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 中定义的 not,但是子类应该定义它,如果他们想要预处理给定协议的请求。

此方法(如果已定义)将由父 OpenerDirector 调用。 req 将是一个 Request 对象。返回值应该是 Request 对象。

BaseHandler.protocol_response(req, response)

此方法是在 BaseHandler 中定义的 not,但是子类应该定义它,如果他们想要对给定协议的后处理响应。

此方法(如果已定义)将由父 OpenerDirector 调用。 req 将是一个 Request 对象。 response 将是一个实现与 urlopen() 的返回值相同的接口的对象。返回值应该实现与 urlopen() 的返回值相同的接口。

21.6.4. 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。此方法由父 OpenerDirector 在获取HTTP“永久移动”响应时调用。

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() 相同,但呼吁“临时重定向”响应。

21.6.5. HTTPCookieProcessor对象

HTTPCookieProcessor 实例具有一个属性:

HTTPCookieProcessor.cookiejar

存储Cookie的 http.cookiejar.CookieJar

21.6.6. ProxyHandler对象

ProxyHandler.protocol_open(request)

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

21.6.7. H asswordMgr对象

这些方法可用于 HTTPPasswordMgrHTTPPasswordMgrWithDefaultRealm 对象。

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

uri 可以是单个URI,也可以是一系列URI。 realmuserpasswd 必须是字符串。这使得当给出针对 realm 和任何给定URI的超URI的认证时,(user, passwd) 用作认证令牌。

HTTPPasswordMgr.find_user_password(realm, authuri)

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

对于 HTTPPasswordMgrWithDefaultRealm 对象,如果给定的 realm 没有匹配的用户/密码,则将搜索领域 None

21.6.8. H asswordMgrWithPriorAuth对象

此密码管理器扩展 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 被忽略。

HTTPPasswordMgr.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 标志的当前状态。

21.6.9. AbstractBasicAuthHandler对象

AbstractBasicAuthHandler.http_error_auth_reqed(authreq, host, req, headers)

通过获取用户/密码对来处理身份验证请求,然后重新尝试请求。 authreq 应该是标题的名称,其中关于领域的信息包括在请求中,host 指定URL和要认证的路径,req 应该是(失败的) Request 对象,并且 headers 应该是错误标头。

host 是权限(例如 "python.org")或包含权限组件(例如 "http://python.org/")的URL。在任一种情况下,该权限不能包含一个userinfo组件(因此,"python.org""python.org:80" 是正确的,"joe:password@python.org" 不是)。

21.6.10. HTTPBasicAuthHandler对象

HTTPBasicAuthHandler.http_error_401(req, fp, code, msg, hdrs)

使用验证信息重试请求(如果可用)。

21.6.11. ProxyBasicAuthHandler对象

ProxyBasicAuthHandler.http_error_407(req, fp, code, msg, hdrs)

使用验证信息重试请求(如果可用)。

21.6.12. AbstractDigestAuthHandler对象

AbstractDigestAuthHandler.http_error_auth_reqed(authreq, host, req, headers)

authreq 应该是头部的名称,其中关于领域的信息包括在请求中,host 应该是要认证的主机,req 应该是(失败的) Request 对象,headers 应该是错误头部。

21.6.13. HTTPDigestAuthHandler对象

HTTPDigestAuthHandler.http_error_401(req, fp, code, msg, hdrs)

使用验证信息重试请求(如果可用)。

21.6.14. ProxyDigestAuthHandler对象

ProxyDigestAuthHandler.http_error_407(req, fp, code, msg, hdrs)

使用验证信息重试请求(如果可用)。

21.6.15. HTTPHandler对象

HTTPHandler.http_open(req)

发送HTTP请求,可以是GET或POST,具体取决于 req.has_data()

21.6.16. HTTPSHandler对象

HTTPSHandler.https_open(req)

发送HTTPS请求,可以是GET或POST,取决于 req.has_data()

21.6.17. FileHandler对象

FileHandler.file_open(req)

如果没有主机名,或者主机名是 'localhost',请在本地打开文件。

在 3.2 版更改: 此方法仅适用于本地主机名。当给出远程主机名时,会引发 URLError

21.6.18. DataHandler对象

DataHandler.data_open(req)

读取数据网址。这种类型的URL包含在URL本身中编码的内容。数据URL语法在 RFC 2397 中指定。此实现忽略base64编码数据URL中的空格,因此URL可能会包含在任何源文件中。但是即使有些浏览器不介意在base64编码数据URL的末尾缺少填充,这种实现会在这种情况下提高 ValueError

21.6.19. FTPHandler对象

FTPHandler.ftp_open(req)

打开 req 指示的FTP文件。登录始终使用空用户名和密码。

21.6.20. CacheFTPHandler对象

CacheFTPHandler 对象是 FTPHandler 对象,具有以下附加方法:

CacheFTPHandler.setTimeout(t)

将连接的超时设置为 t 秒。

CacheFTPHandler.setMaxConns(m)

设置到 m 的缓存连接的最大数量。

21.6.21. UnknownHandler对象

UnknownHandler.unknown_open()

引发 URLError 异常。

21.6.22. HTTPErrorProcessor对象

HTTPErrorProcessor.http_response()

处理HTTP错误响应。

对于200个错误代码,将立即返回响应对象。

对于非200错误代码,这只是通过 OpenerDirector.error() 将作业传递到 protocol_error_code() 处理程序方法。最终,如果没有其他处理程序处理错误,HTTPDefaultErrorHandler 将抛出一个 HTTPError

HTTPErrorProcessor.https_response()

处理HTTPS错误响应。

行为与 http_response() 相同。

21.6.23. 例子

除了下面的实施例,在 如何使用urllib包获取Internet资源 中给出了更多的实施例。

此示例获取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网站使用其元标记中指定的 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() 提供许多处理程序,包括 ProxyHandler。默认情况下,ProxyHandler 使用名为 <scheme>_proxy 的环境变量,其中 <scheme> 是涉及的URL方案。例如,读取 http_proxy 环境变量以获取HTTP代理的URL。

此示例将默认 ProxyHandler 替换为使用以编程方式提供的代理URL的默认 ProxyHandler,并使用 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输出的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("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')
...

21.6.24. 传统接口

以下函数和类从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('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 报头报告的大小)时,urlretrieve() 将引发 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方法。如果方案未被识别,则调用 open_unknown()data 参数具有与 urlopen()data 参数相同的含义。

open_unknown(fullurl, data=None)

可覆盖的界面,用于打开未知的URL类型。

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

检索 url 的内容并将其放置在 filename 中。返回值是由本地文件名和包含响应头(用于远程URL)或 None (用于本地URL)的 email.message.Message 对象组成的元组。然后调用者必须打开并读取 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

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

class urllib.request.FancyURLopener(...)

3.3 版后已移除.

FancyURLopener 子类 URLopener 为以下HTTP响应代码提供默认处理:301,302,303,307和401.对于上面列出的30x响应代码,Location 标头用于获取实际的URL。对于401响应代码(需要认证),将执行基本的HTTP认证。对于30x响应代码,递归由 maxtries 属性的值限定,默认值为10。

对于所有其他响应代码,调用方法 http_error_default(),您可以在子类中覆盖以适当地处理错误。

注解

根据 RFC 2616 的信件,301和302响应POST请求不得自动重定向,没有用户的确认。实际上,浏览器允许自动重定向这些响应,将POST改为GET,urllib 再现此行为。

构造函数的参数与 URLopener 的参数相同。

注解

当执行基本认证时,FancyURLopener 实例调用其 prompt_user_passwd() 方法。默认实现向用户询问控制终端上所需的信息。如果需要,子类可以覆盖此方法以支持更适当的行为。

FancyURLopener 类提供一个额外的方法,应该重载以提供适当的行为:

prompt_user_passwd(host, realm)

返回在指定安全领域中的给定主机上认证用户所需的信息。返回值应该是一个元组,(user, password),可以用于基本认证。

实现在终端上提示此信息;应用程序应覆盖此方法以在本地环境中使用适当的交互模型。

21.6.25. urllib.request 限制

  • 目前,仅支持以下协议:HTTP(版本0.9和1.0),FTP,本地文件和数据URL。

    在 3.4 版更改: 添加了对数据网址的支持。

  • 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 以满足您的需求。

21.7. urllib.response — urllib使用的响应类

urllib.response 模块定义了定义类似接口的最小文件的函数和类,包括 read()readline()。典型的响应对象是一个addinfourl实例,它定义了一个 info() 方法,并返回标题和一个返回url的 geturl() 方法。此模块定义的函数由 urllib.request 模块在内部使用。