httplib2 是一个功能强大的 HTTP 客户端库,它支持 HTTP 和 HTTPS 协议,并且以其缓存功能而闻名,这意味着它会自动将下载的响应内容存储在本地,下次请求相同资源时,可以直接从本地读取,大大加快了速度并减少了对服务器的请求。
安装 httplib2
你需要确保已经安装了 httplib2,如果尚未安装,可以通过 pip 进行安装:
pip install httplib2
基本下载流程
使用 httplib2 下载文件的基本步骤如下:
- 导入库:
import httplib2 - 创建 Http 实例:
http = httplib2.Http(),这个对象会处理所有的网络请求和响应。 - 发送请求:
response, content = http.request(url, 'GET'),这是核心步骤,它会向指定 URL 发送一个 GET 请求。response: 是一个类字典对象,包含了服务器的响应头信息,如状态码、内容类型、内容长度等。content: 是一个字节串,包含了服务器返回的响应体内容(也就是文件内容)。
- 检查响应状态码: 在下载前,应该检查
response['status']是否为200(OK),以确保请求成功。 - :
- 如果下载的是文本文件(如 HTML, JSON),可以直接将
content解码为字符串。 - 如果下载的是二进制文件(如图片、PDF、视频),
content就是文件的原始二进制数据,需要将其写入一个文件。
- 如果下载的是文本文件(如 HTML, JSON),可以直接将
完整代码示例
下面是一个完整的、可以直接运行的示例,它演示了如何下载一张网络图片并保存到本地。
import httplib2
def download_file_with_httplib2(url, save_path):
"""
使用 httplib2 从指定 URL 下载文件并保存到本地。
:param url: 要下载的文件的 URL
:param save_path: 保存文件的本地路径
"""
print(f"开始下载: {url}")
# 1. 创建一个 Http 实例
# 你可以在这里配置缓存目录, http = httplib2.Http(".cache")
http = httplib2.Http()
try:
# 2. 发送 GET 请求
# response 是响应头,content 是响应内容的字节流
response, content = http.request(url, 'GET')
# 3. 检查请求是否成功 (HTTP 状态码 200)
if response.status == 200:
print("请求成功,开始保存文件...")
# 4. 将二进制内容写入文件
# 使用 'wb' 模式以二进制写入方式打开文件
with open(save_path, 'wb') as f:
f.write(content)
print(f"文件已成功保存至: {save_path}")
else:
print(f"下载失败,服务器返回状态码: {response.status}")
print(f"响应头信息: {response}")
except httplib2.HttpLib2Error as e:
print(f"发生网络或 HTTP 错误: {e}")
except Exception as e:
print(f"发生未知错误: {e}")
# --- 使用示例 ---
if __name__ == "__main__":
# 要下载的文件 URL (这里使用一张示例图片)
file_url = "https://www.python.org/static/community_logos/python-logo-master-v3-TM.png"
# 本地保存的文件名和路径
local_file_path = "python_logo.png"
# 调用下载函数
download_file_with_httplib2(file_url, local_file_path)
如何运行:
- 将上述代码保存为
download.py文件。 - 确保你已经安装了
httplib2(pip install httplib2)。 - 在终端中运行
python download.py。 - 运行后,你会在同一目录下看到一个名为
python_logo.png的文件。
进阶用法
1 使用缓存 (httplib2 的核心优势)
httplib2 的一个巨大优点是内置了缓存机制,当你再次请求同一个 URL 时,它会先检查本地缓存,如果缓存有效且未过期,它会直接从缓存返回内容,而不会重新发起网络请求。
import httplib2
import os
def download_with_cache(url, save_path, cache_dir=".httplib2_cache"):
"""
使用带缓存的 httplib2 下载文件。
"""
# 确保缓存目录存在
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
print(f"使用缓存目录: {cache_dir}")
# 创建 Http 实例,并指定缓存目录
http = httplib2.Http(cache_dir)
response, content = http.request(url, 'GET')
if response.status == 200:
# 注意:即使从缓存读取,http.request 也会返回 content
# httplib2 会自动处理缓存的新鲜度(stale-while-revalidate 等)
print("文件获取成功 (可能来自缓存或网络)。")
with open(save_path, 'wb') as f:
f.write(content)
print(f"文件已保存至: {save_path}")
# 你可以查看缓存目录,会发现里面多了缓存文件
print(f"缓存文件位于: {cache_dir}")
else:
print(f"下载失败,状态码: {response.status}")
# --- 使用示例 ---
if __name__ == "__main__":
file_url = "https://www.python.org/static/community_logos/python-logo-master-v3-TM.png"
local_file_path = "python_logo_cached.png"
# 第一次下载 (会从网络获取)
print("--- 第一次下载 ---")
download_with_cache(file_url, local_file_path)
print("\n" + "="*30 + "\n")
# 第二次下载 (会直接从缓存读取,速度极快)
print("--- 第二次下载 (应来自缓存) ---")
download_with_cache(file_url, local_file_path)
2 添加请求头
有时,你需要添加自定义的请求头,例如模拟浏览器访问或设置认证信息。
import httplib2
def download_with_headers(url, save_path):
http = httplib2.Http()
# 定义请求头
headers = {
'User-Agent': 'MyCoolDownloader/1.0 (compatible; MSIE 10.0; Windows NT 6.2)',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5'
}
# 发送请求时传入 headers 参数
response, content = http.request(url, 'GET', headers=headers)
if response.status == 200:
with open(save_path, 'wb') as f:
f.write(content)
print(f"文件已保存至: {save_path}")
else:
print(f"下载失败,状态码: {response.status}")
# --- 使用示例 ---
if __name__ == "__main__":
file_url = "https://httpbin.org/user-agent" # 一个可以测试 User-Agent 的网站
local_file_path = "user_agent_response.html"
download_with_headers(file_url, local_file_path)
httplib2 vs. requests
在现代 Python 开发中,requests 库因其简洁的 API 和人性化的设计而更受欢迎,对于简单的下载任务,requests 通常更易于使用。
| 特性 | httplib2 |
requests |
|---|---|---|
| API 设计 | 较底层,直接返回 (response, content) 元组 |
高级,更符合 Pythonic 风格,如 response.text, response.json() |
| 缓存 | 内置强大缓存功能 | 不内置缓存,需要自己实现或使用第三方库 |
| 易用性 | 较低,需要手动处理更多细节 | 非常高,API 直观,文档清晰 |
| 依赖 | 标准库 email 和 urllib |
依赖 urllib3 和 chardet |
| 推荐场景 | 需要精细控制缓存、或进行底层 HTTP 操作的场景 | 绝大多数 Web 请求场景,包括文件下载 |
使用 requests 下载文件的对比代码:
import requests
def download_with_requests(url, save_path):
try:
# stream=True 表示流式下载,适合大文件
# 它不会一次性将整个文件加载到内存
with requests.get(url, stream=True) as r:
r.raise_for_status() # 如果状态码不是 200,则抛出异常
with open(save_path, 'wb') as f:
# 分块写入文件,避免内存爆炸
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
print(f"文件已成功保存至: {save_path}")
except requests.exceptions.RequestException as e:
print(f"下载失败: {e}")
# --- 使用示例 ---
if __name__ == "__main__":
file_url = "https://www.python.org/static/community_logos/python-logo-master-v3-TM.png"
local_file_path = "python_logo_requests.png"
download_with_requests(file_url, local_file_path)
- 如果你只需要简单地下载一个文件,并且不关心缓存,
requests是更简单、更现代的选择。 - 如果你需要缓存功能,或者在一个对性能要求极高、需要减少重复网络请求的场景中,
httplib2是一个非常优秀的选择。 - 对于初学者来说,
requests的学习曲线更平缓,推荐作为首选的 HTTP 客户端库。
