21.6. urllib.request — 用于打开 URL 的可扩展库 — Python 文档
21.6. urllib.request — 用于打开 URL 的可扩展库
源代码: :source:`Lib/urllib/request.py`
urllib.request 模块定义了有助于在复杂世界中打开 URL(主要是 HTTP)的函数和类——基本和摘要认证、重定向、cookie 等等。
urllib.request 模块定义了以下函数:
- urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
打开 URL url,它可以是字符串或 Request 对象。
data 必须是指定要发送到服务器的附加数据的对象,如果不需要此类数据,则为
None
。 有关详细信息,请参阅 请求 。urllib.request 模块使用 HTTP/1.1 并在其 HTTP 请求中包含
Connection:close
标头。可选的 timeout 参数指定阻塞操作(如连接尝试)的超时(以秒为单位)(如果未指定,将使用全局默认超时设置)。 这实际上仅适用于 HTTP、HTTPS 和 FTP 连接。
如果指定了 context,它必须是一个描述各种 SSL 选项的 ssl.SSLContext 实例。 有关更多详细信息,请参阅 HTTPSConnection。
可选的 cafile 和 capath 参数为 HTTPS 请求指定一组受信任的 CA 证书。 cafile 应该指向包含一组 CA 证书的单个文件,而 capath 应该指向散列证书文件的目录。 更多信息可以在 ssl.SSLContext.load_verify_locations() 中找到。
cadefault 参数被忽略。
此函数始终返回一个对象,该对象可以作为 上下文管理器 并具有诸如
geturl()
— 返回检索到的资源的 URL,通常用于确定是否遵循重定向info()
— 以 email.message_from_string() 实例的形式返回页面的元信息,例如标题(参见 快速参考 HTTP 标头 ) )getcode()
– 返回响应的 HTTP 状态代码。
对于 HTTP 和 HTTPS URL,此函数返回一个稍作修改的 http.client.HTTPResponse 对象。 除了上述三个新方法之外,msg 属性包含与 reason 属性相同的信息 - 服务器返回的原因短语 - 而不是 文档中指定的响应标头HTTPResponse。
对于由遗留 URLopener 和 FancyURLopener 类显式处理的 FTP、文件和数据 URL 和请求,此函数返回一个
urllib.response.addinfourl
对象。在协议错误时引发 URLError。
请注意,如果没有处理程序处理请求,则可能会返回
None
(尽管默认安装的全局 OpenerDirector 使用 UnknownHandler 来确保这永远不会发生)。此外,如果检测到代理设置(例如,当设置了
http_proxy
等*_proxy
环境变量时),则默认安装 ProxyHandler 并且确保通过代理处理请求。Python 2.6 及更早版本中的遗留
urllib.urlopen
函数已停止使用; urllib.request.urlopen() 对应旧的urllib2.urlopen
。 代理处理是通过将字典参数传递给urllib.urlopen
来完成的,可以使用 ProxyHandler 对象获得。3.2 版更改:添加了 cafile 和 capath。
在 3.2 版中更改:如果可能,现在支持 HTTPS 虚拟主机(即,如果 ssl.HAS_SNI 为真)。
3.2 新功能: data 可以是一个可迭代对象。
在 3.3 版更改:添加了 cadefault。
在 3.4.3 版更改:添加了 上下文 。
自 3.6 版起已弃用:cafile、capath 和 cadefault 已弃用,取而代之的是 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 实例,它按照给定的顺序链接处理程序。 handlers 可以是 BaseHandler 的实例,也可以是 BaseHandler 的子类(在这种情况下,必须可以不带任何参数调用构造函数)。 以下类的实例将位于 handlers 的前面,除非 handlers 包含它们、它们的实例或它们的子类:ProxyHandler(如果检测到代理设置)、UnknownHandler、HTTPHandler、HTTPDefaultErrorHandler、HTTPRedirectHandler、FTPHandler、[XFileHandler4X] 、HTTPErrorProcessor。
如果 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
的变量的环境,不区分大小写,当找不到时,从 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 应该是一个包含有效 URL 的字符串。
data 必须是指定要发送到服务器的附加数据的对象,如果不需要此类数据,则为
None
。 目前 HTTP 请求是唯一使用 data 的请求。 支持的对象类型包括字节、类文件对象和可迭代对象。 如果没有提供Content-Length
和Transfer-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 文档中的图像,而用户没有选择批准自动获取图像的选项,则这应该是正确的。method 应该是一个字符串,表示将使用的 HTTP 请求方法(例如
'HEAD'
)。 如果提供,其值存储在 method 属性中,并由 get_method() 使用。 如果 data 为None
或'POST'
,则默认为'GET'
否则。 子类可以通过在类本身中设置 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 设置部分获取,而在 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)
这是一个混合类,有助于对远程主机和代理进行 HTTP 身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西; 有关必须支持的接口的信息,请参阅部分 HTTPPasswordMgr 对象 。 如果 passwd_mgr 还提供
is_authenticated
和update_authenticated
方法(参见 HTTPPasswordMgrWithPriorAuth Objects),则处理程序将使用is_authenticated
结果一个给定的 URI,以确定是否随请求发送身份验证凭据。 如果is_authenticated
为 URI 返回True
,则发送凭据。 如果is_authenticated
是False
,则不发送凭据,然后如果收到401
响应,则请求会与身份验证凭据一起重新发送。 如果认证成功,则调用update_authenticated
为 URI 设置is_authenticated
True
,以便对该 URI 或其任何超级 URI 的后续请求将自动包含认证凭据.3.5 新功能: 添加
is_authenticated
支持。
- class urllib.request.HTTPBasicAuthHandler(password_mgr=None)
- 处理与远程主机的身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西; 有关必须支持的接口的信息,请参阅部分 HTTPPasswordMgr 对象 。 当出现错误的身份验证方案时,HTTPBasicAuthHandler 将引发 ValueError。
- class urllib.request.ProxyBasicAuthHandler(password_mgr=None)
- 使用代理处理身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西; 有关必须支持的接口的信息,请参阅部分 HTTPPasswordMgr 对象 。
- class urllib.request.AbstractDigestAuthHandler(password_mgr=None)
- 这是一个混合类,有助于对远程主机和代理进行 HTTP 身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西; 有关必须支持的接口的信息,请参阅部分 HTTPPasswordMgr 对象 。
- class urllib.request.HTTPDigestAuthHandler(password_mgr=None)
处理与远程主机的身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西; 有关必须支持的接口的信息,请参阅部分 HTTPPasswordMgr 对象 。 当同时添加摘要式身份验证处理程序和基本身份验证处理程序时,总是首先尝试摘要式身份验证。 如果摘要式身份验证再次返回 40x 响应,则将其发送到基本身份验证处理程序进行处理。 当使用 Digest 或 Basic 以外的身份验证方案时,此 Handler 方法将引发 ValueError。
在 3.3 版更改:在不受支持的身份验证方案上引发 ValueError。
- class urllib.request.ProxyDigestAuthHandler(password_mgr=None)
- 使用代理处理身份验证。 password_mgr,如果给出,应该是与 HTTPPasswordMgr 兼容的东西; 有关必须支持的接口的信息,请参阅部分 HTTPPasswordMgr 对象 。
- class urllib.request.HTTPHandler
- 处理打开 HTTP URL 的类。
- class urllib.request.HTTPSHandler(debuglevel=0, context=None, check_hostname=None)
处理打开 HTTPS URL 的类。 context 和 check_hostname 与 http.client.HTTPSConnection 具有相同的含义。
3.2 版更改:添加了 context 和 check_hostname。
- class urllib.request.FileHandler
- 打开本地文件。
- class urllib.request.DataHandler
打开数据 URL。
3.4 版中的新功能。
- class urllib.request.FTPHandler
- 打开 FTP URL。
- class urllib.request.CacheFTPHandler
- 打开 FTP URL,保留打开的 FTP 连接的缓存以最大程度地减少延迟。
- class urllib.request.UnknownHandler
- 处理未知 URL 的全能类。
- class urllib.request.HTTPErrorProcessor
- 处理 HTTP 错误响应。
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
- 布尔值,指示请求是否如 RFC 2965 所定义的那样不可验证。
- Request.method
要使用的 HTTP 请求方法。 默认情况下,它的值为 None,这意味着 get_method() 将对要使用的方法进行正常计算。 可以设置它的值(从而覆盖 get_method() 中的默认计算),方法是通过在 Request 子类中的类级别设置它来提供默认值,或者通过传递一个通过 method 参数将值输入到 Request 构造函数中。
3.3 版中的新功能。
3.4 版本更改:现在可以在子类中设置默认值; 以前它只能通过构造函数参数设置。
- Request.get_method()
返回一个字符串,指示 HTTP 请求方法。 如果 Request.method 不是
None
,则返回其值,否则返回'GET'
如果 Request.data 是None
,或者'POST'
如果不是。 这仅对 HTTP 请求有意义。3.3 版更改: get_method 现在查看 Request.method 的值。
- Request.add_header(key, val)
- 向请求添加另一个标头。 当前,除 HTTP 处理程序之外的所有处理程序都忽略标头,将它们添加到发送到服务器的标头列表中。 注意同名的header不能超过一个,如果key冲突,后面的调用会覆盖之前的调用。 目前,这并没有丢失 HTTP 功能,因为所有在多次使用时有意义的标头都有一种(标头特定的)方式来仅使用一个标头获得相同的功能。
- Request.add_unredirected_header(key, header)
- 添加不会添加到重定向请求的标头。
- Request.has_header(header)
- 返回实例是否具有命名标头(检查常规和未重定向)。
- Request.remove_header(header)
从请求实例中删除命名标头(从常规标头和未重定向标头中)。
3.4 版中的新功能。
- Request.get_full_url()
返回构造函数中给出的 URL。
在 3.4 版中更改。
- Request.set_proxy(host, type)
- 通过连接到代理服务器来准备请求。 host 和 type 将替换实例的那些,并且实例的选择器将是构造函数中给出的原始 URL。
- Request.get_header(header_name, default=None)
- 返回给定标头的值。 如果标题不存在,则返回默认值。
- Request.header_items()
- 返回请求标头的元组列表 (header_name, header_value)。
3.4 版更改: 自 3.3 起已弃用的请求方法 add_data、has_data、get_data、get_type、get_host、get_selector、get_origin_req_host 和 is_unverifiable 已被删除。
21.6.2. OpenerDirector 对象
OpenerDirector 实例有以下方法:
- OpenerDirector.add_handler(handler)
- handler 应该是 BaseHandler 的一个实例。 搜索以下方法,并将其添加到可能的链中(注意 HTTP 错误是一种特殊情况)。
protocol_open()
— 表示处理程序知道如何打开 协议 URL。http_error_type()
— 表示处理程序知道如何处理 HTTP 错误代码为 type 的 HTTP 错误。protocol_error()
— 表示处理程序知道如何处理来自(非http
)协议的错误。protocol_request()
— 表示处理程序知道如何预处理 协议 请求。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_*()
方法。返回值和引发的异常与 urlopen() 的相同。
OpenerDirector 对象分三个阶段打开 URL:
在每个阶段中调用这些方法的顺序是通过对处理程序实例进行排序来确定的。
每个具有名为
protocol_request()
的方法的处理程序都会调用该方法来预处理请求。调用具有类似
protocol_open()
方法的处理程序来处理请求。 当处理程序返回非 None 值(即 响应),或引发异常(通常为 URLError)。 允许异常传播。实际上,上述算法首先是针对名为
default_open()
的方法进行尝试的。 如果所有这些方法都返回 None,则对命名为protocol_open()
之类的方法重复该算法。 如果所有这些方法都返回 None,则对名为unknown_open()
的方法重复该算法。请注意,这些方法的实现可能涉及调用父 OpenerDirector 实例的 open() 和 error() 方法。
每个具有名为
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中定义的而不是,但是子类如果想要捕获所有的URL就应该定义它。
这个方法,如果实现了,会被父级 OpenerDirector 调用。 它应该返回一个类似文件的对象,如 OpenerDirector 或
None
的 open() 的返回值中所述。 它应该引发 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() 的返回值相同的接口。
21.6.4. HTTPRedirectHandler 对象
笔记
某些 HTTP 重定向需要来自此模块的客户端代码的操作。 如果是这种情况,则会引发 HTTPError。 有关各种重定向代码的确切含义的详细信息,请参阅 RFC 2616。
如果 HTTPRedirectHandler 呈现的重定向 URL 不是 HTTP、HTTPS 或 FTP URL,则会作为安全考虑引发 HTTPError
异常。
- HTTPRedirectHandler.redirect_request(req, fp, code, msg, hdrs, newurl)
返回 Request 或
None
以响应重定向。 当从服务器收到重定向时,http_error_30*()
方法的默认实现会调用它。 如果应该发生重定向,返回一个新的 Request 以允许http_error_30*()
执行重定向到 newurl。 否则,如果没有其他处理程序应该尝试处理此 URL,则引发 HTTPError,如果您不能但另一个处理程序可能会尝试处理,则返回None
。笔记
此方法的默认实现并没有严格遵循 RFC 2616,其中规定对
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() 相同,但调用“临时重定向”响应。
21.6.6. ProxyHandler 对象
- ProxyHandler.protocol_open(request)
- ProxyHandler 将有一个方法
protocol_open()
用于每个 protocol,它在构造函数中给出的 proxies 字典中有一个代理。 该方法将修改请求通过代理,通过调用request.set_proxy()
,并调用链中的下一个处理程序来实际执行协议。
21.6.7. HTTPPasswordMgr 对象
这些方法在 HTTPPasswordMgr 和 HTTPPasswordMgrWithDefaultRealm 对象上可用。
- HTTPPasswordMgr.add_password(realm, uri, user, passwd)
- uri 可以是单个 URI,也可以是一个 URI 序列。 realm、user 和 passwd 必须是字符串。 这会导致
(user, passwd)
在 realm 的身份验证和任何给定 URI 的超级 URI 被给定时用作身份验证令牌。
- HTTPPasswordMgr.find_user_password(realm, authuri)
获取给定领域和 URI 的用户/密码(如果有)。 如果没有匹配的用户/密码,此方法将返回
(None, None)
。对于 HTTPPasswordMgrWithDefaultRealm 对象,如果给定的 realm 没有匹配的用户/密码,将搜索领域
None
。
21.6.8. 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。
- 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"
) 或包含授权组件的 URL(例如"http://python.org/%22
)。 在任何一种情况下,权限都不能包含用户信息组件(因此,"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.file_open(req)
在本地打开文件,如果没有主机名,或者主机名是
'localhost'
。3.2 版本变更:此方法仅适用于本地主机名。 当给出远程主机名时,会引发 URLError。
21.6.18. 数据处理器对象
- DataHandler.data_open(req)
- 读取数据 URL。 这种 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.22。 HTTPErrorProcessor 对象
- HTTPErrorProcessor.http_response(request, response)
处理 HTTP 错误响应。
对于 200 个错误代码,立即返回响应对象。
对于非 200 错误代码,这只是通过 OpenerDirector.error() 将作业传递给
protocol_error_code()
处理程序方法。 最终,如果没有其他处理程序处理错误, HTTPDefaultErrorHandler 将引发 HTTPError。
- HTTPErrorProcessor.https_response(request, response)
处理 HTTPS 错误响应。
行为与 http_response() 相同。
21.6.23。 例子
除了下面的例子,更多例子在HOWTO Fetch Internet Resources Using The urllib Package中给出。
此示例获取 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
也可以在不使用 上下文管理器 方法的情况下实现相同的结果。
>>> 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 的代理程序,并使用 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 标头:
将 headers 参数用于 Request 构造函数,或:
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 时添加了一些标准标头(Content-Length、Content-Type 和 Host)到 urlopen()(或 OpenerDirector.open())。
以下是使用 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 是任何info()
方法的urlopen() 返回的对象返回(对于远程对象)。 例外情况与 urlopen() 相同。第二个参数(如果存在)指定要复制到的文件位置(如果不存在,该位置将是具有生成名称的临时文件)。 第三个参数(如果存在)是一个可调用对象,它将在建立网络连接时调用一次,之后在每个块读取后调用一次。 callable 将传递三个参数; 到目前为止传输的块数、块大小(以字节为单位)以及文件的总大小。 第三个参数可能是
-1
在较旧的 FTP 服务器上,这些服务器不响应检索请求返回文件大小。以下示例说明了最常见的使用场景:
>>> import urllib.request >>> local_filename, headers = urllib.request.urlretrieve('http://python.org/') >>> html = open(local_filename) >>> html.close()
如果 url 使用
http:
方案标识符,则可以提供可选的 data 参数来指定POST
请求(通常请求类型为 [ X168X])。 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/VVV
的 User-Agent 标头,其中 VVV 是 urllib 版本数字。 应用程序可以通过子类化 URLopener 或 FancyURLopener 并将类属性 version 设置为适当的字符串值来定义自己的 User-Agent 标头子类定义。可选的 proxies 参数应该是将方案名称映射到代理 URL 的字典,其中空字典完全关闭代理。 它的默认值为
None
,在这种情况下,将使用环境代理设置(如果存在),如上面 urlopen() 的定义中所述。x509 中收集的附加关键字参数可用于在使用
https:
方案时对客户端进行身份验证。 支持关键字 key_file 和 cert_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 中。 返回值是一个元组,由本地文件名和包含响应标头的 email.message.Message 对象(对于远程 URL)或
None
(对于本地 URL)组成。 然后调用者必须打开并读取 filename 的内容。 如果未给出 filename 并且 URL 引用本地文件,则返回输入文件名。 如果 URL 是非本地的且未给出 filename,则文件名是 tempfile.mktemp() 的输出,后缀与最后一个路径组件的后缀匹配输入网址。 如果给出了 reporthook,它必须是一个接受三个数字参数的函数:块号、读入的最大大小块和下载的总大小(如果未知,则为 -1)。 它将在开始时和从网络读取每个数据块后调用一次。 reporthook 被本地 URL 忽略。如果 url 使用
http:
方案标识符,则可以提供可选的 data 参数来指定POST
请求(通常请求类型为 [ X168X])。 data 参数必须是标准的 application/x-www-form-urlencoded 格式; 参见 urllib.parse.urlencode() 函数。
- version
指定 opener 对象的用户代理的变量。 要让 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 的信函,对 POST 请求的 301 和 302 响应不得在未经用户确认的情况下自动重定向。 实际上,浏览器确实允许自动重定向这些响应,将 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 版更改: 添加了对数据 URL 的支持。
urlretrieve() 的缓存功能已被禁用,直到有人找到时间来破解 Expiration 时间标头的正确处理。
应该有一个函数来查询特定的 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()
方法并返回标头和一个 geturl()
方法返回 URL。 该模块定义的函数由 urllib.request 模块内部使用。