urllib2 是 Python 2 标准库中用于打开 URL(主要是 HTTP)的模块,当访问需要用户名和密码的网站时,就需要进行身份认证。

核心概念
在 urllib2 中,认证主要通过两个核心类来实现:
urllib2.HTTPBasicAuthHandler: 处理 HTTP 基本认证,这是一种简单但不太安全的认证方式,用户名和密码经过 Base64 编码后发送给服务器,但没有加密。urllib2.HTTPDigestAuthHandler: 处理 HTTP 摘要认证,比基本认证更安全,因为它不会在网络中直接传输密码,而是传输一个“。
工作流程
使用 urllib2 进行认证的标准流程如下:
- 创建一个密码管理器 (
HTTPPasswordMgrWithDefaultRealm):这个对象用于存储 URL、用户名和密码的映射关系。 - 添加凭据:将需要认证的 URL、用户名和密码添加到密码管理器中。
- 创建一个认证处理器 (
HTTPBasicAuthHandler或HTTPDigestAuthHandler):将密码管理器与认证处理器关联起来。 - 创建一个opener (
build_opener):使用urllib2.build_opener()方法,将认证处理器添加到其中,创建一个可以处理认证的“opener”。 - 安装opener (
install_opener):可选步骤,将这个自定义的 opener 安装为全局默认的 opener,之后所有urllib2.urlopen()调用都会自动使用这个 opener。 - 打开URL:使用
urlopen()打开需要认证的 URL,如果服务器返回401 Unauthorized错误,认证处理器会自动从密码管理器中查找凭据并重试请求。
示例代码
下面我们通过两个具体的例子来演示如何实现基本认证和摘要认证。
示例 1: HTTP 基本认证
假设我们要访问一个需要基本认证的网站 http://example.com/protected,用户名是 user,密码是 pass。

import urllib2
import base64
# --- 方法一:直接在 Request 中添加 Authorization 头 ---
def auth_method_1():
print "--- 使用方法一 (直接添加头) ---"
url = 'http://example.com/protected' # 替换为实际的URL
username = 'user'
password = 'pass'
# 创建一个 Request 对象
request = urllib2.Request(url)
# 将用户名和密码拼接成 "username:password" 的格式
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
# 创建 Authorization 头,格式为 "Basic base64string"
request.add_header("Authorization", "Basic %s" % base64string)
try:
response = urllib2.urlopen(request)
print "Response Code:", response.getcode()
print "Response Body:", response.read()
except urllib2.HTTPError as e:
print "Error Code:", e.code
print "Error Reason:", e.reason
except urllib2.URLError as e:
print "URLError:", e.reason
# --- 方法二:使用 HTTPBasicAuthHandler (推荐) ---
def auth_method_2():
print "\n--- 使用方法二 (推荐使用 AuthHandler) ---"
url = 'http://example.com/protected' # 替换为实际的URL
username = 'user'
password = 'pass'
# 1. 创建密码管理器
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
# 2. 添加凭据
# 第一个参数是 "域" (realm),如果不知道,可以使用 None
# 这表示这个用户名/密码可以用于任何需要认证的 URL
password_mgr.add_password(None, url, username, password)
# 3. 创建认证处理器
handler = urllib2.HTTPBasicAuthHandler(password_mgr)
# 4. 创建 opener
opener = urllib2.build_opener(handler)
# 5. (可选) 安装 opener 为全局默认
# 之后所有的 urllib2.urlopen 调用都会使用这个 opener
urllib2.install_opener(opener)
# 6. 打开 URL
# 如果服务器返回 401,handler 会自动使用 password_mgr 中的凭据重试
try:
response = urllib2.urlopen(url)
print "Response Code:", response.getcode()
print "Response Body:", response.read()
except urllib2.HTTPError as e:
print "Error Code:", e.code
print "Error Reason:", e.reason
except urllib2.URLError as e:
print "URLError:", e.reason
# 运行示例
if __name__ == '__main__':
# 注意:你需要将 'http://example.com/protected' 替换成一个真实存在的、需要认证的URL
# auth_method_1()
# auth_method_2()
pass
代码解释:
- 方法一:手动构建
Authorization头,这种方式简单直接,但不够灵活,如果一个站点有多个需要认证的路径,你需要为每个路径都手动处理。 - 方法二:这是
urllib2推荐的方式。HTTPBasicAuthHandler会自动处理401错误,并尝试你提供的凭据,它更加模块化和可重用。
示例 2: HTTP 摘要认证
认证的流程与基本认证类似,只是将 HTTPBasicAuthHandler 换成 HTTPDigestAuthHandler。
import urllib2
def digest_auth_example():
print "--- HTTP 摘要认证示例 ---"
url = 'http://example.com/digest-protected' # 替换为实际的URL
username = 'user'
password = 'pass'
# 1. 创建密码管理器
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
# 2. 添加凭据
password_mgr.add_password(None, url, username, password)
# 3. 创建认证处理器 (使用 Digest 而不是 Basic)
handler = urllib2.HTTPDigestAuthHandler(password_mgr)
# 4. 创建 opener
opener = urllib2.build_opener(handler)
# 5. 打开 URL
try:
response = opener.open(url)
print "Response Code:", response.getcode()
print "Response Body:", response.read()
except urllib2.HTTPError as e:
print "Error Code:", e.code
print "Error Reason:", e.reason
except urllib2.URLError as e:
print "URLError:", e.reason
# 运行示例
if __name__ == '__main__':
# digest_auth_example()
pass
处理代理认证
如果你需要通过一个需要认证的代理服务器访问互联网,过程也非常相似,只是使用 ProxyBasicAuthHandler 和 ProxyDigestAuthHandler。
import urllib2
def proxy_auth_example():
print "--- 代理认证示例 ---"
# 目标 URL
url = 'http://www.example.com'
# 代理服务器地址和端口
proxy_url = 'http://proxy.example.com:8080'
# 代理服务器用户名和密码
proxy_user = 'proxy_user'
proxy_pass = 'proxy_pass'
# 1. 创建密码管理器
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
# 2. 添加代理凭据
# 注意 add_password 的第二个参数是代理的 URL
password_mgr.add_password(None, proxy_url, proxy_user, proxy_pass)
# 3. 创建代理认证处理器
proxy_handler = urllib2.ProxyBasicAuthHandler(password_mgr)
# 4. (可选) 创建一个普通处理器,用于处理非代理请求
# 如果不添加,opener 可能无法直接连接目标 URL
# opener = urllib2.build_opener(proxy_handler) # 这样可能不够
opener = urllib2.build_opener(proxy_handler, urllib2.ProxyHandler({})) # 更稳妥
# 5. 安装 opener
urllib2.install_opener(opener)
# 6. 打开目标 URL
# 请求会先通过代理,代理认证处理器会自动处理
try:
response = urllib2.urlopen(url)
print "Response Code:", response.getcode()
print "Response Body:", response.read()
except urllib2.HTTPError as e:
print "Error Code:", e.code
print "Error Reason:", e.reason
except urllib2.URLError as e:
print "URLError:", e.reason
# 运行示例
if __name__ == '__main__':
# proxy_auth_example()
pass
重要提示:Python 3 的迁移
Python 2 已经停止维护,强烈建议你迁移到 Python 3。
在 Python 3 中,urllib2 被重构并拆分到了 urllib.request 和 urllib.error 等模块中,认证的逻辑基本保持不变,只是模块名和导入方式变了。
Python 3 对比示例:
# Python 3 代码
import urllib.request
import urllib.error
import base64
# 基本认证 (方法二)
url = 'http://example.com/protected'
username = 'user'
password = 'pass'
# 1. 创建密码管理器
password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# 2. 添加凭据
password_mgr.add_password(None, url, username, password)
# 3. 创建认证处理器
handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
# 4. 创建 opener
opener = urllib.request.build_opener(handler)
# 5. 安装 opener
# urllib.request.install_opener(opener) # 可选
# 6. 打开 URL
try:
# 注意:在 Python 3 中,urlopen 返回的是一个 bytes 对象,需要解码
response = opener.open(url)
print("Response Code:", response.getcode())
print("Response Body:", response.read().decode('utf-8'))
except urllib.error.HTTPError as e:
print("Error Code:", e.code)
print("Error Reason:", e.reason)
except urllib.error.URLError as e:
print("URLError:", e.reason)
| 功能 | Python 2 (urllib2) |
Python 3 (urllib.request) |
|---|---|---|
| 基本认证处理器 | HTTPBasicAuthHandler |
HTTPBasicAuthHandler |
| 密码管理器 | HTTPPasswordMgrWithDefaultRealm |
HTTPPasswordMgrWithDefaultRealm |
| 构建 Opener | build_opener() |
build_opener() |
| 打开 URL | urlopen() |
urlopen() |
| 导入模块 | import urllib2 |
import urllib.request |
掌握 urllib2 的认证方法对于 Python 2 的开发很重要,但请务必将学习重点转向 Python 3 及其 urllib.request 模块。
