http.client 教程-如何使用 Python 标准库发送 HTTP 请求
以下是 http.client 模块的详细使用教程,帮助你理解如何使用 Python 标准库发送 HTTP 请求:
1. http.client 概述
http.client 是 Python 内置的 HTTP 客户端库,提供了底层的 HTTP 协议实现,支持:
- 发送 HTTP/1.1 请求
- 处理响应状态码、头信息和内容
- 支持 HTTPS(通过 HTTPSConnection)
- 支持基本认证、Cookie 等功能
优点:无需额外安装依赖,适合轻量级 HTTP 交互。
缺点:API 较为底层,使用复杂度高于 requests 库。
2. 基本使用流程
步骤 1:导入模块并创建连接
import http.client # HTTP 连接 conn = http.client.HTTPConnection("example.com") # HTTPS 连接(默认端口 443) conn = http.client.HTTPSConnection("api.example.com") # 指定端口(如 8080) conn = http.client.HTTPConnection("localhost", 8080) |
步骤 2:发送请求
# 发送 GET 请求 conn.request("GET", "/path/to/resource") # 发送带参数的 GET 请求 conn.request("GET", "/search?q=python&page=1") # 发送 POST 请求(带 JSON 数据) headers = {"Content-Type": "application/json"} body = '{"name": "test", "age": 30}' conn.request("POST", "/users", body, headers) |
步骤 3:获取响应
response = conn.getresponse() # 获取响应状态码 status_code = response.status # 如 200, 404, 500 # 获取响应头 headers = response.getheaders() # 获取响应内容 data = response.read() # 返回 bytes 类型 text = data.decode("utf-8") # 转为字符串 |
步骤 4:关闭连接
conn.close() |
3. 处理不同类型的请求
GET 请求示例
import http.client conn = http.client.HTTPSConnection("jsonplaceholder.typicode.com") conn.request("GET", "/posts/1") response = conn.getresponse() print(f"状态码: {response.status}") print(f"响应头: {response.getheaders()}") print(f"响应内容: {response.read().decode()}") conn.close() |
POST 请求示例(JSON 数据)
import http.client import json conn = http.client.HTTPSConnection("jsonplaceholder.typicode.com") headers = {"Content-Type": "application/json"} body = json.dumps({"title": "foo", "body": "bar", "userId": 1}) conn.request("POST", "/posts", body, headers) response = conn.getresponse() print(response.read().decode()) conn.close() |
带参数的 POST 请求(表单数据)
import http.client from urllib.parse import urlencode conn = http.client.HTTPConnection("example.com") headers = {"Content-Type": "application/x-www-form-urlencoded"} params = urlencode({"username": "test", "password": "123456"}) conn.request("POST", "/login", params, headers) response = conn.getresponse() print(response.read().decode()) conn.close() |
4. 处理响应
响应状态码
if response.status == 200: print("请求成功") elif response.status == 404: print("资源不存在") else: print(f"错误: {response.status}") |
响应头处理
# 获取特定头信息 content_type = response.getheader("Content-Type") print(f"内容类型: {content_type}") # 获取所有头信息 headers = response.getheaders() for header, value in headers: print(f"{header}: {value}") |
响应内容处理
# 读取二进制内容 data = response.read() # 根据 Content-Type 解码 content_type = response.getheader("Content-Type") if "json" in content_type: import json json_data = json.loads(data) elif "text" in content_type: text = data.decode("utf-8") else: # 二进制数据(如图像、文件) with open("file.bin", "wb") as f: f.write(data) |
5. 高级用法
设置超时时间
conn = http.client.HTTPSConnection("example.com", timeout=5) # 5秒超时 |
处理重定向(301/302)
max_redirects = 3 current_url = "/initial-path" redirect_count = 0 while redirect_count < max_redirects: conn.request("GET", current_url) response = conn.getresponse()
if response.status in (301, 302): location = response.getheader("Location") current_url = location redirect_count += 1 else: break # 非重定向状态码,退出循环 |
设置请求头(如 User-Agent)
headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept": "application/json" } conn.request("GET", "/api/data", headers=headers) |
基本认证
import base64 username = "admin" password = "secret" auth_string = f"{username}:{password}" auth_bytes = base64.b64encode(auth_string.encode()) auth_header = f"Basic {auth_bytes.decode()}" headers = {"Authorization": auth_header} conn.request("GET", "/protected", headers=headers) |
6. 异常处理
import http.client try: conn = http.client.HTTPSConnection("nonexistent-domain.com") conn.request("GET", "/") response = conn.getresponse() except ConnectionRefusedError: print("连接被拒绝") except TimeoutError: print("连接超时") except http.client.InvalidURL: print("无效的 URL") except Exception as e: print(f"发生错误: {e}") finally: if conn: conn.close() |
7. 完整示例:获取天气 API 数据
import http.client import json try: # 连接到天气API conn = http.client.HTTPSConnection("api.openweathermap.org") # API参数(城市ID和API密钥) city_id = "1850147" # 东京的城市ID api_key = "YOUR_API_KEY" # 替换为你的API密钥 # 发送请求 conn.request("GET", f"/data/2.5/weather?id={city_id}&appid={api_key}") # 获取响应 response = conn.getresponse() if response.status == 200: data = json.loads(response.read().decode()) print(f"城市: {data['name']}") print(f"天气: {data['weather'][0]['description']}") print(f"温度: {data['main']['temp'] - 273.15:.1f}°C") # 转为摄氏度 else: print(f"错误: {response.status} - {response.read().decode()}") except Exception as e: print(f"发生异常: {e}") finally: conn.close() |
8. 与 requests 库对比
特性 | http.client | requests |
所属库 | Python 标准库(无需安装) | 第三方库(需 pip install) |
API 复杂度 | 底层,需要手动处理很多细节 | 高层,简洁易用 |
请求方法 | request() 结合方法参数 | get(), post(), put() 等 |
响应处理 | 手动解析状态码、头和内容 | 自动解析,提供 json() 方法 |
会话管理 | 需手动管理连接 | 自动管理会话(如 Cookie) |
重定向处理 | 需手动实现 | 自动处理(可配置) |
文件上传 | 复杂 | 简单(files 参数) |
9. 常见问题解答
- Q1:如何设置请求超时?
A:在创建连接时指定 timeout 参数,如 HTTPSConnection("example.com", timeout=10)。
- Q2:如何处理 HTTPS 证书验证?
A:默认验证证书。若需忽略,使用 context 参数:
import ssl context = ssl._create_unverified_context() conn = http.client.HTTPSConnection("example.com", context=context) |
- Q3:如何发送大文件?
A:使用分块传输(Chunked Transfer),需设置 Transfer-Encoding: chunked 头,手动分块发送。
通过这个教程,你应该能够掌握 http.client 的基本使用方法。在实际项目中,若追求更高的开发效率,推荐使用 requests 库;若需要底层控制或环境受限(如无第三方库),则 http.client 是更好的选择。