20.5. urllib —pass URL 打开任意资源

Note

urllib模块已拆分为多个部分,并在 Python 3 中重命名为urllib.requesturllib.parseurllib.error。将您的源转换为 Python 3 时,2to3工具将自动适应导入。另外请注意,Python 3 中的urllib.request.urlopen()函数等效于urllib2.urlopen(),并且已删除了urllib.urlopen()

该模块提供了一个高级界面,用于在 www 上获取数据。特别地,urlopen()函数类似于内置函数open(),但是接受通用资源定位符(URL)而不是文件名。适用一些限制-它只能打开 URL 进行读取,而没有搜索操作可用。

See also

推荐使用Requests package作为更高级别的 HTTPClient 端界面。

在版本 2.7.9 中更改:对于 HTTPS URI,默认情况下urllib执行所有必要的证书和主机名检查。

Warning

对于 2.7.9 之前的 Python 版本,urllib 不会try验证 HTTPS URI 的服务器证书。使用风险自负!

20.5.1. 高级界面

除了info()getcode()geturl()方法外,这些方法与文件对象具有相同的接口-请参见本手册的File Objects部分。 (但是,它不是内置文件对象,因此无法在需要 true 的内置文件对象的少数地方使用.)

info()方法返回包含与 URL 关联的元信息的mimetools.Message类的实例。当方法为 HTTP 时,这些 Headers 是服务器在检索到的 HTML 页面的顶部返回的 Headers(包括 Content-Length 和 Content-Type)。当该方法是 FTP 时,如果服务器(如现在通常)响应 FTP 检索请求而传递了文件长度,则将出现 Content-LengthHeaders。如果可以猜测 MIME 类型,则将显示 Content-TypeHeaders。当该方法为本地文件时,返回的 Headers 将包括代表文件的最后修改时间的日期,提供文件大小的 Content-Length 以及包含对文件类型的猜测的 Content-Type。另请参见mimetools模块的说明。

geturl()方法返回页面的真实 URL。在某些情况下,HTTP 服务器会将 Client 端重定向到另一个 URL。 urlopen()函数透明地处理此问题,但是在某些情况下,调用者需要知道 Client 端重定向到的 URL。 geturl()方法可用于获取此重定向的 URL。

getcode()方法返回与响应一起发送的 HTTP 状态代码,如果 URL 不是 HTTP URL,则返回None

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

urlopen()函数与不需要身份验证的代理透明地一起工作。在 Unix 或 Windows 环境中,在启动 Python 解释器之前,将 http_proxy ftp_proxy环境变量设置为标识代理服务器的 URL。例如('%'是命令提示符):

% http_proxy="http://www.someproxy.com:3128"
% export http_proxy
% python
...

no_proxy环境变量可用于指定不应pass代理访问的主机;如果设置的话,它应该是主机名后缀的逗号分隔列表,可以选择附加:port,例如cern.ch,ncsa.uiuc.edu,some.host:8080

在 Windows 环境中,如果未设置代理环境变量,则将从注册表的“ Internet 设置”部分获取代理设置。

在 Mac OS X 环境中,urlopen()将从 OS X 系统配置框架检索代理信息,该信息可pass“网络系统偏好设置”面板进行 Management。

或者,可选的* proxies *参数可用于显式指定代理。它必须是将代理名称 Map 到代理 URL 的字典,其中空字典不会使用任何代理,并且None(默认值)会导致使用环境代理设置,如上所述。例如:

# Use http://www.someproxy.com:3128 for HTTP proxying
proxies = {'http': 'http://www.someproxy.com:3128'}
filehandle = urllib.urlopen(some_url, proxies=proxies)
# Don't use any proxies
filehandle = urllib.urlopen(some_url, proxies={})
# Use proxies from environment - both versions are equivalent
filehandle = urllib.urlopen(some_url, proxies=None)
filehandle = urllib.urlopen(some_url)

当前不支持需要身份验证才能使用的代理;这被认为是实施限制。

在版本 2.3 中进行了更改:添加了代理支持。

在 2.6 版中进行了更改:将getcode()添加到返回的对象中,并支持 no_proxy环境变量。

在版本 2.7.9 中更改:添加了* context *参数。默认情况下,所有必要的证书和主机名检查均已完成。

自 2.6 版起弃用:urlopen()函数已在 Python 3 中删除,以urllib2.urlopen()的形式删除。

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

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

在版本 2.5 中进行了更改:当urlretrieve()检测到可用数据量小于预期量(这是* Content-Length *Headers 报告的大小)时,它将引发ContentTooShortError。例如,当下载break时,可能会发生这种情况。

在这种情况下,您仍然可以检索下载的数据,该数据存储在异常实例的content属性中。

如果未提供* Content-Length *Headers,则urlretrieve()无法检查其已下载数据的大小,只能返回它。在这种情况下,您只需要假设下载成功即可。

在版本 2.7.9 中更改:添加了* context *参数。默认情况下,所有必要的证书和主机名检查均已完成。

import urllib

class AppURLopener(urllib.FancyURLopener):
    version = "App/1.7"

urllib._urlopener = AppURLopener()

20.5.2. 实用Function

示例:quote('/~connolly/')产生'/%7econnolly/'

示例:unquote('/%7Econnolly/')产生'/~connolly/'

Note

如果设置了环境变量REQUEST_METHOD(通常表示您的脚本在 CGI 环境中运行),则将忽略环境变量HTTP_PROXY(大写_PROXY)。这是因为 Client 端可以使用“ Proxy:” HTTPHeaders 注入该变量。如果需要在 CGI 环境中使用 HTTP 代理,则可以显式使用ProxyHandler,或确保变量名称为小写(或至少为_proxy后缀)。

Note

urllib 还公开了某些 Util Function,例如 splittype,splithost 和其他将 URL 解析为各种组件的Function。但是建议使用urlparse来解析 URL,而不是直接使用这些函数。 Python 3 并未从urllib.parse模块公开这些帮助函数。

20.5.3. URL Opener 对象

默认情况下,URLopener类发送urllib/VVV的* User-Agent Headers,其中 VVV urllib版本号。应用程序可以pass将URLopenerFancyURLopener子类化并将类属性version设置为子类定义中的适当字符串值来定义自己的 User-Agent *Headers。

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

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

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

在版本 2.7.9 中更改:添加了* context *参数。默认情况下,所有必要的证书和主机名检查均已完成。

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

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

Note

根据 RFC 2616的字母,未经用户确认,不得自动重定向 POST 请求的响应 301 和 302.实际上,浏览器确实允许自动重定向这些响应,将 POST 更改为 GET,并且urllib重现此行为。

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

Note

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

FancyURLopener类提供了另一种方法,应重载以提供适当的行为:

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

2.5 版的新Function。

20.5.4. urllib 限制

Note

20.5.5. Examples

这是使用GET方法检索包含参数的 URL 的示例会话:

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params)
>>> print f.read()

下面的示例改为使用POST方法:

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query", params)
>>> print f.read()

下面的示例使用一个显式指定的 HTTP 代理,它覆盖环境设置:

>>> import urllib
>>> proxies = {'http': 'http://proxy.example.com:8080/'}
>>> opener = urllib.FancyURLopener(proxies)
>>> f = opener.open("http://www.python.org")
>>> f.read()

以下示例完全不使用代理,覆盖环境设置:

>>> import urllib
>>> opener = urllib.FancyURLopener({})
>>> f = opener.open("http://www.python.org/")
>>> f.read()
首页