Python urllib:将代理路由与网站 Basic 认证合并
在一个显式 opener 中合并 urllib 路由与目标站点的 Basic 认证,而不必两次替换全局 opener。
调用 install_opener() 两次并不会把第二个 opener 添加到第一个上,而是替换模块的默认 opener。如果一个对象知道代理,另一个对象知道网站登录信息,就构建一个包含所需 handler 的单一 opener。
import os
from urllib.request import (ProxyHandler, HTTPBasicAuthHandler,
HTTPPasswordMgrWithDefaultRealm, build_opener)
passwords = HTTPPasswordMgrWithDefaultRealm()
passwords.add_password(None, 'https://example.com/private/',
os.environ['SITE_USER'], os.environ['SITE_PASSWORD'])
opener = build_opener(
ProxyHandler({'https': 'http://203.0.113.10:8080'}),
HTTPBasicAuthHandler(passwords),
)
with opener.open('https://example.com/private/report', timeout=10) as response:
body = response.read()代理和目的地只是示例。对于可通过公共 HTTP 代理访问的公共服务,HTTP 代理列表为路由 handler 提供候选端点。这个 opener 通过 HTTP 代理路由 HTTPS 请求,并处理目的地的 Basic 质询。它不配置代理认证。
如果代理本身也需要登录,请另行选择受支持的代理认证方案。在 CONNECT 阶段出现的 407 早于目的地发出自己的质询。把网站凭据加入密码管理器无法满足更早的那次交换。
直接调用 opener.open() 可以让配置与操作放在一起。除非应用有意让所有便捷调用共用这个 opener,否则无需修改模块级默认值。