核心概念
在 Python 2 中,urllib2 是用于打开 URL(主要是 HTTP)的标准库,它比 urllib 更强大,提供了更高级的功能,比如处理 HTTP 认证、cookies、代理等。

发送 GET 请求的本质是:向服务器发送一个 HTTP 请求,其中请求方法为 GET,并且参数通常直接附加在 URL 的后面(http://example.com?key1=value1&key2=value2)。
最简单直接的方法
这是最基本的方式,适用于发送不带任何额外请求头或参数的简单 GET 请求。
代码示例
# 导入 urllib2 库
import urllib2
# 1. 定义目标 URL
# 注意:这里使用一个支持 JSON 的测试 API,方便查看结果
url = "http://httpbin.org/get"
try:
# 2. 发送请求并获取响应
# urlopen() 会返回一个文件类的对象,我们可以像读取文件一样读取它
response = urllib2.urlopen(url)
# 3. 读取响应内容
# response.read() 会返回响应体的内容(通常是字符串)
html_content = response.read()
# 4. 打印响应内容
print "Status Code:", response.getcode() # 获取 HTTP 状态码
print "Response Headers:", response.headers # 获取响应头
print "Response Content:"
print html_content
except urllib2.URLError, e:
# 处理可能发生的 URL 错误,例如网络连接问题、域名不存在等
print "We failed to reach a server."
print "Reason: ", e.reason
except urllib2.HTTPError, e:
# 处理 HTTP 错误,404 (Not Found), 500 (Server Error) 等
print "We failed with an error code - %s" % e.code
print "Error Page:", e.read() # 读取错误页面的内容
代码解析
import urllib2: 导入所需的库。urllib2.urlopen(url): 这是核心函数,它接收一个 URL 字符串作为参数,向该 URL 发送一个默认的 GET 请求,并返回一个addinfourl对象(类似于文件对象)。response.read(): 从响应对象中读取服务器返回的全部内容,对于网页,通常是 HTML 代码;对于 API,通常是 JSON 或 XML 数据。response.getcode(): 获取 HTTP 状态码,200(成功),404(未找到),500(服务器内部错误)。response.headers: 获取服务器的响应头信息。try...except: 网络请求是脆弱的,可能会因为各种原因失败(如无网络、服务器宕机、URL 错误等),使用try...except来捕获这些异常是良好的编程习惯。urllib2.HTTPError: 处理 HTTP 协议层面的错误(4xx, 5xx)。urllib2.URLError: 处理更广泛的 URL 错误(如 DNS 解析失败、连接拒绝),HTTPError是URLError的子类。
带参数和请求头的 GET 请求
在实际开发中,我们经常需要向 URL 添加查询参数(如 ?name=John&age=30),或者自定义请求头(如 User-Agent)。
如何处理 URL 参数?
手动拼接:对于简单的参数,可以直接用字符串拼接。
url = "http://httpbin.org/get?name=Alice&age=25"

推荐方法 - urlencode:更安全、更规范,它会自动处理特殊字符(如空格、&、)的编码,避免产生错误的 URL。
如何添加请求头?
我们需要创建一个 Request 对象,而不是直接使用 urlopen(url),在 Request 对象中,我们可以指定 URL、数据、请求头等。
代码示例
import urllib
import urllib2
# 1. 定义基础 URL
base_url = "httphttp://httpbin.org/get"
# 2. 定义要发送的参数(字典格式)
params = {
'name': '王小明',
'age': 30,
'city': '北京'
}
# 3. 使用 urlencode 将字典编码为 URL 查询字符串
# 结果会是 "name=%E7%8E%8B%E5%B0%8F%E6%98%8E&age=30&city=%E5%8C%97%E4%BA%AC"
query_string = urllib.urlencode(params)
# 4. 将查询字符串拼接到 URL 后面
# 注意:base_url 本身已经有参数,需要手动处理 '?' 和 '&' 的拼接
final_url = base_url + "?" + query_string
print "Final URL:", final_url
# 5. 创建 Request 对象
# 我们可以添加自定义的请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
'Accept': 'application/json' # 告诉服务器我们期望接收 JSON 格式的数据
}
request = urllib2.Request(final_url, headers=headers)
try:
# 6. 发送请求
response = urllib2.urlopen(request)
# 7. 读取并打印响应
print "\nResponse Content:"
# httpbin.org/get 返回的 JSON 中会包含你发送的请求信息,可以验证我们的请求是否正确
print response.read()
except urllib2.HTTPError, e:
print "Error Code:", e.code
except urllib2.URLError, e:
print "Reason:", e.reason
代码解析
import urllib: 我们需要urllib库中的urlencode函数。params = {...}: 将 GET 参数定义为一个字典,这是最清晰的方式。urllib.urlencode(params): 将字典转换为key=value&key=value格式的字符串,并自动进行 URL 编码。final_url = base_url + "?" + query_string: 将编码后的查询字符串拼接到 URL。headers = {...}: 定义一个字典来存放自定义的请求头。urllib2.Request(final_url, headers=headers): 创建一个Request对象,传入最终的 URL 和请求头。urllib2.urlopen(request): 使用Request对象来发送请求,而不是直接使用 URL。
总结与重要提示
| 特性 | 方法 | 说明 |
|---|---|---|
| 简单 GET | urllib2.urlopen("http://...") |
最直接,适用于无参数、无特殊需求的请求。 |
| 带参数/Header | urllib2.Request(...) |
更灵活,是处理复杂请求的标准方式。 |
| URL 编码 | urllib.urlencode() |
必须使用!用于安全地将字典参数转换为 URL 查询字符串。 |
| 异常处理 | try...except urllib2.HTTPError, URLError |
必须使用!保证程序的健壮性。 |
Python 3 的重要提示
urllib2 是 Python 2 的库,在 Python 3 中,urllib 和 urllib2 被整合并重构成了 urllib 包。
urllib2.urlopen()->urllib.request.urlopen()urllib2.Request()->urllib.request.Request()urllib.urlencode()->urllib.parse.urlencode()
如果你正在学习 Python,强烈建议直接学习 Python 3,下面是上面第二个例子在 Python 3 中的写法,对比一下会发现语法非常相似:

# Python 3 版本
import urllib.request
import urllib.parse
base_url = "http://httpbin.org/get"
params = {'name': '王小明', 'age': 30, 'city': '北京'}
query_string = urllib.parse.urlencode(params)
final_url = base_url + "?" + query_string
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
'Accept': 'application/json'
}
request = urllib.request.Request(final_url, headers=headers)
try:
with urllib.request.urlopen(request) as response: # 使用 with 语句可以自动关闭响应
print("Status Code:", response.getcode())
content = response.read().decode('utf-8') # 读取 bytes 并解码为字符串
print("Response Content:")
print(content)
except urllib.error.HTTPError as e:
print("Error Code:", e.code)
except urllib.error.URLError as e:
print("Reason:", e.reason) 