urllib.request
— 用于打开 URL 的可扩展库¶
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.SSLContext
实例,描述各种 SSL 选项。有关详细信息,请参阅HTTPSConnection
。此函数始终返回一个可以作为 context manager 工作的对象,并具有 *url*、*headers* 和 *status* 属性。有关这些属性的更多详细信息,请参阅
urllib.response.addinfourl
。对于 HTTP 和 HTTPS URL,此函数返回一个经过轻微修改的
http.client.HTTPResponse
对象。除了上述三个新方法外,msg 属性包含与reason
属性相同的信息 — 服务器返回的原因短语 — 而不是HTTPResponse
文档中指定的响应头部。对于 FTP、文件和数据 URL,此函数返回
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 会使用请求对象中的
fullurl
、data
、headers
、method
参数引发一个 审计事件urllib.Request
。3.3 版中已更改: 增加了 *cadefault*。
3.4.3 版中已更改: 增加了 *context*。
3.10 版中已更改: 如果未给出 *context*,HTTPS 连接现在会发送带有协议指示符
http/1.1
的 ALPN 扩展。自定义 *context* 应使用set_alpn_protocols()
设置 ALPN 协议。3.13 版中已更改: 移除了 *cafile*、*capath* 和 *cadefault* 参数:请改用 *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* 之前,除非 *handler* 包含它们、它们的实例或它们的子类:ProxyHandler
(如果检测到代理设置)、UnknownHandler
、HTTPHandler
、HTTPDefaultErrorHandler
、HTTPRedirectHandler
、FTPHandler
、FileHandler
、HTTPErrorProcessor
。如果 Python 安装支持 SSL(即如果可以导入
ssl
模块),则还会添加HTTPSHandler
。一个
BaseHandler
子类也可以更改其handler_order
属性来修改其在处理程序列表中的位置。
- urllib.request.pathname2url(path, *, add_scheme=False)¶
将给定的本地路径转换为
file:
URL。此函数使用quote()
函数编码路径。如果 *add_scheme* 为 false (默认值),则返回值省略
file:
方案前缀。将 *add_scheme* 设置为 true 以返回完整的 URL。此示例显示了该函数在 Windows 上的使用
>>> from urllib.request import pathname2url >>> path = 'C:\\Program Files' >>> pathname2url(path, add_scheme=True) 'file:///C:/Program%20Files'
3.14 版中已更改: Windows 驱动器盘符不再转换为大写,并且不跟随驱动器盘符的
:
字符在 Windows 上不再引发OSError
异常。3.14 版中已更改: 以斜杠开头的路径将转换为带有授权部分的 URL。例如,路径
/etc/hosts
将转换为 URL///etc/hosts
。3.14 版中已更改: 添加了 *add_scheme* 参数。
- urllib.request.url2pathname(url, *, require_scheme=False, resolve_host=False)¶
将给定的
file:
URL 转换为本地路径。此函数使用unquote()
解码 URL。如果 *require_scheme* 为假(默认值),则给定值应省略
file:
方案前缀。如果 *require_scheme* 设置为真,则给定值应包含前缀;如果它不包含,则会引发URLError
。如果 URL 授权为空、
localhost
或本地主机名,则会丢弃。否则,如果 *resolve_host* 设置为真,则使用socket.gethostbyname()
解析授权并在匹配本地 IP 地址时丢弃(根据 RFC 8089 §3)。如果授权仍未处理,则在 Windows 上返回 UNC 路径,在其他平台上引发URLError
。此示例显示了该函数在 Windows 上的使用
>>> from urllib.request import url2pathname >>> url = 'file:///C:/Program%20Files' >>> url2pathname(url, require_scheme=True) 'C:\\Program Files'
3.14 版中已更改: Windows 驱动器盘符不再转换为大写,并且不跟随驱动器盘符的
:
字符在 Windows 上不再引发OSError
异常。3.14 版中已更改: 如果 URL 授权与本地主机名匹配,则会丢弃。否则,如果授权不为空或
localhost
,则在 Windows 上返回 UNC 路径(与之前一样),在其他平台上引发URLError
。3.14 版中已更改: 如果存在,则丢弃 URL 查询和片段组件。
3.14 版中已更改: 添加了 *require_scheme* 和 *resolve_host* 参数。
- urllib.request.getproxies()¶
此辅助函数返回一个方案到代理服务器 URL 映射的字典。它首先以不区分大小写的方式扫描所有操作系统中名为
<scheme>_proxy
的变量,如果找不到,则从 macOS 的系统配置和 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
将用于发送字节对象,而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()
使用。如果 *data* 为None
,则默认值为'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.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
的领域视为包罗万象的领域,并对其进行搜索。
- 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 对象),则处理程序将使用给定 URI 的is_authenticated
结果来确定是否随请求发送认证凭据。如果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 对象 一节。3.14 版中已更改: 增加了对 HTTP 摘要认证算法
SHA-256
的支持。
- 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 的类。*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 错误响应。
请求对象¶
以下方法描述了 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.data¶
请求的实体正文,如果未指定则为
None
。3.4 版中已更改: 更改
Request.data
的值现在会删除之前设置或计算的“Content-Length”头部。
- Request.method¶
要使用的 HTTP 请求方法。默认情况下,其值为
None
,这意味着get_method()
将正常计算要使用的方法。可以通过在Request
子类中在类级别设置它来提供默认值(从而覆盖get_method()
中的默认计算),或者通过 *method* 参数将值传递给Request
构造函数来设置。在 3.3 版本加入。
3.4 版中已更改: 现在可以在子类中设置默认值;以前只能通过构造函数参数设置。
- Request.get_method()¶
返回一个字符串,指示 HTTP 请求方法。如果
Request.method
不是None
,则返回其值,否则如果Request.data
为None
,则返回'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.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 已移除。
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()
— 表示处理程序知道如何处理来自(非http
)*protocol* 的错误。<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:
在每个阶段中调用这些方法的顺序由处理程序实例的排序决定。
每个具有名为
<protocol>_request()
的方法的处理程序都会调用该方法来预处理请求。命名为
<protocol>_open()
的处理器被调用来处理请求。当处理器返回一个非None
值(即一个响应),或者引发一个异常(通常是URLError
)时,此阶段结束。异常允许传播。实际上,上述算法首先尝试名为
default_open()
的方法。如果所有此类方法都返回None
,则算法将对名为<protocol>_open()
的方法重复执行。如果所有此类方法都返回None
,则算法将对名为unknown_open()
的方法重复执行。请注意,这些方法的实现可能涉及调用父
OpenerDirector
实例的open()
和error()
方法。每个具有名为
<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
调用。它应返回一个文件类对象,如OpenerDirector
的open()
方法的返回值所述,或者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
自动调用,通常不应在其他情况下调用。OpenerDirector
将使用五个位置参数调用此方法一个
Request
对象,一个带有 HTTP 错误正文的文件类对象,
错误的三位数字代码,作为字符串,
用户可见的代码解释,作为字符串,以及
错误头,作为映射对象。
返回值和引发的异常应与
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 收到一个不是 HTTP、HTTPS 或 FTP URL 的重定向 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,该 RFC 规定对
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 版本中新增。
ProxyHandler 对象¶
- ProxyHandler.<protocol>_open(request)
ProxyHandler
将为构造函数中给定 proxies 字典中具有代理的每个 protocol 提供一个<protocol>_open()
方法。该方法将通过调用request.set_proxy()
来修改请求以通过代理,并调用链中的下一个处理器来实际执行协议。
HTTPPasswordMgr 对象¶
这些方法适用于 HTTPPasswordMgr
和 HTTPPasswordMgrWithDefaultRealm
对象。
- 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)¶
- 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://pythonlang.cn/"
)。在这两种情况下,权威机构都不得包含用户信息组件(因此,"python.org"
和"python.org:80"
是可以的,"joe:password@python.org"
不可以)。
HTTPBasicAuthHandler 对象¶
- HTTPBasicAuthHandler.http_error_401(req, fp, code, msg, hdrs)¶
如果可用,使用身份验证信息重试请求。
ProxyBasicAuthHandler 对象¶
- ProxyBasicAuthHandler.http_error_407(req, fp, code, msg, hdrs)¶
如果可用,使用身份验证信息重试请求。
AbstractDigestAuthHandler 对象¶
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.data
。
HTTPSHandler 对象¶
- HTTPSHandler.https_open(req)¶
发送一个 HTTPS 请求,它可以是 GET 或 POST,具体取决于
req.data
。
FileHandler 对象¶
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 对象¶
HTTPErrorProcessor 对象¶
- HTTPErrorProcessor.http_response(request, response)¶
处理 HTTP 错误响应。
对于 200 错误代码,响应对象会立即返回。
对于非 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>\n<!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"> <![endif]-->\n<!--[if IE 7]> <html class="no-js ie7 lt-ie8 lt-ie9"> <![endif]-->\n<!--[if IE 8]> <html class="no-js ie8 lt-ie9">
请注意,urlopen 返回一个字节对象。这是因为 urlopen 无法自动确定从 HTTP 服务器接收到的字节流的编码。通常,程序会在确定或猜测出适当的编码后,将返回的字节对象解码为字符串。
以下 HTML 规范文档 https://html.whatwg.cn/#charset 列出了 HTML 或 XML 文档可能指定其编码信息的各种方式。
有关更多信息,请参阅 W3C 文档:https://www.w3.org/International/questions/qa-html-encoding-declarations。
由于 python.org 网站在其 meta 标签中指定使用 *utf-8* 编码,因此我们将使用相同的编码来解码字节对象。
>>> with urllib.request.urlopen('https://pythonlang.cn/') as f:
... print(f.read(100).decode('utf-8'))
...
<!doctype html>
<!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"> <![endif]-->
<!-
也可以不使用 上下文管理器 方法实现相同的结果。
>>> import urllib.request
>>> f = urllib.request.urlopen('https://pythonlang.cn/')
>>> try:
... print(f.read(100).decode('utf-8'))
... finally:
... f.close()
...
<!doctype html>
<!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"> <![endif]-->
<!--
在以下示例中,我们将数据流发送到 CGI 的 stdin,并读取它返回给我们的数据。请注意,此示例仅在 Python 安装支持 SSL 时才有效。
>>> import urllib.request
>>> req = urllib.request.Request(url='https:///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://: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)
with urllib.request.urlopen('http://www.example.com/login.html') as f:
print(f.read().decode('utf-8'))
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:
with opener.open('http://www.example.com/login.html') as f:
print(f.read().decode('utf-8'))
添加 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: . . .)')
with urllib.request.urlopen(req) as f:
print(f.read().decode('utf-8'))
OpenerDirector
会自动为每个 Request
添加一个 *User-Agent* 标头。要更改此设置
import urllib.request
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
with opener.open('http://www.example.com/') as f:
print(f.read().decode('utf-8'))
另外,请记住,当 Request
传递给 urlopen()
(或 OpenerDirector.open()
)时,会添加一些标准标头(*Content-Length*、*Content-Type* 和 *Host*)。
这是一个使用 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 输出的参数在发送到 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.build_opener(urllib.request.ProxyHandler(proxies))
>>> with opener.open("https://pythonlang.cn") as f:
... f.read().decode('utf-8')
...
以下示例完全不使用代理,覆盖环境设置。
>>> import urllib.request
>>> opener = urllib.request.build_opener(urllib.request.ProxyHandler({}}))
>>> 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, 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()
可能留下的临时文件。
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
模块。
urllib.response
— urllib 使用的响应类¶
urllib.response
模块定义了函数和类,它们定义了一个最小的文件类接口,包括 read()
和 readline()
。此模块定义的函数由 urllib.request
模块内部使用。典型的响应对象是 urllib.response.addinfourl
实例。