网络通信的基石:Python HTTP请求库完全解析

🔎大家好,我是ZTLJQ,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流

📝个人主页-ZTLJQ的主页

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​📣系列果你对这个系列感兴趣的话

专栏 - ​​​​​​Python从零到企业级应用:短时间成为市场抢手的程序员

✔说明⇢本人讲解主要包括Python爬虫、JS逆向、Python的企业级应用

如果你对这个系列感兴趣的话,可以关注订阅哟👋

为什么需要专门的HTTP库?

Python内置的urllib模块功能强大,但其API相对底层且繁琐。想象一下,为了发送一个带自定义头部和超时设置的POST请求,你需要写上十几行代码...

幸运的是,社区诞生了像requests这样被誉为"人类为人类创造的HTTP库"。它以简洁、优雅的API彻底改变了Python的网络编程格局。

本篇博客将带你从基础到高级,全面掌握requests和它的现代化继任者httpx,并对比它们与urllib的差异。


第一部分:requests - 无可争议的王者

requests (pip install requests) 因其极简的API和强大的功能,成为了事实上的标准。

1.1 基础请求方法
python 复制代码
import requests

# ---- GET 请求:获取数据 ----
response = requests.get('https://httpbin.org/get')

# 检查响应状态
if response.status_code == 200:
    print("请求成功!")
else:
    print(f"请求失败,状态码: {response.status_code}")

# 获取响应内容
print(response.text) # 字符串形式
# print(response.content) # 字节形式 (bytes),对于图片等二进制数据有用

# 将JSON响应直接解析为Python字典
json_data = response.json()
print(json_data['url']) # https://httpbin.org/get

# ---- POST 请求:发送数据 ----
# 发送表单数据 (application/x-www-form-urlencoded)
form_data = {'key1': 'value1', 'key2': 'value2'}
post_response = requests.post('https://httpbin.org/post', data=form_data)

# 发送JSON数据 (application/json)
json_payload = {'name': 'Alice', 'age': 30}
post_json_response = requests.post('https://httpbin.org/post', json=json_payload)

# ---- PUT / DELETE 请求 ----
put_response = requests.put('https://httpbin.org/put', json={'data': 'updated'})
delete_response = requests.delete('https://httpbin.org/delete')

解析 : requests 的核心在于每个HTTP方法(get, post, put, delete)都对应一个同名函数,参数直观。

1.2 关键参数详解
python 复制代码
import requests

# ---- 1. 参数 (params) ----
# 将参数自动附加到URL的查询字符串中
params = {'page': 2, 'size': 10, 'q': 'python tutorial'}
response = requests.get('https://api.example.com/search', params=params)
# 等价于访问: https://api.example.com/search?page=2&size=10&q=python+tutorial

# ---- 2. 自定义头部 (headers) ----
headers = {
    'User-Agent': 'MyApp/1.0',
    'Authorization': 'Bearer your-jwt-token-here', # Bearer Token 认证
    'Content-Type': 'application/json' # 通常由 requests 自动设置
}
response = requests.get('https://api.example.com/data', headers=headers)

# ---- 3. 超时 (timeout) ----
# 非常重要!防止程序无限期等待
try:
    response = requests.get('https://slow-website.com', timeout=5) # 5秒后超时
except requests.exceptions.Timeout:
    print("请求超时!")
except requests.exceptions.RequestException as e:
    print(f"请求出错: {e}")

# ---- 4. 处理重定向 (allow_redirects) ----
# 默认 allow_redirects=True,会自动跟随重定向
# 如果想禁用,设为 False
response = requests.get('http://github.com', allow_redirects=False)
print(response.status_code) # 301
print(response.headers['Location']) # https://github.com

# ---- 5. 会话 (Session) ----
# Session 对象可以跨请求保持 cookies 和 headers,非常高效。
session = requests.Session()
session.headers.update({'User-Agent': 'MyApp/1.0'})

# 登录 (假设这个请求会返回一个 session cookie)
login_data = {'username': 'user', 'password': 'pass'}
session.post('https://example.com/login', data=login_data)

# 后续请求会自动携带登录获得的 cookie
profile_response = session.get('https://example.com/profile')
dashboard_response = session.get('https://example.com/dashboard')

# 最后关闭会话
session.close() # 或使用 with 语句
1.3 实际案例:构建一个简单的REST客户端
python 复制代码
import requests
from typing import Optional, Dict, Any

class APIClient:
    def __init__(self, base_url: str, api_key: str):
        self.base_url = base_url.rstrip('/') # 移除末尾斜杠
        self.session = requests.Session()
        self.session.headers.update({
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        })
    
    def get(self, endpoint: str, params: Optional[Dict] = None) -> Dict[Any, Any]:
        """封装GET请求"""
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        try:
            response = self.session.get(url, params=params, timeout=10)
            response.raise_for_status() # 如果不是2xx状态码,抛出HTTPError
            return response.json()
        except requests.exceptions.HTTPError as e:
            print(f"HTTP错误: {e}")
            if e.response.status_code == 404:
                print("资源未找到")
            elif e.response.status_code == 401:
                print("认证失败")
        except requests.exceptions.RequestException as e:
            print(f"请求异常: {e}")
        return {}
    
    def post(self, endpoint: str, data: Dict) -> Dict[Any, Any]:
        """封装POST请求"""
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        try:
            response = self.session.post(url, json=data, timeout=10)
            response.raise_for_status()
            return response.json() # 假设服务器返回创建的资源
        except Exception as e:
            print(f"POST请求失败: {e}")
            return {}
    
    def close(self):
        """关闭会话"""
        self.session.close()

# 使用客户端
client = APIClient("https://jsonplaceholder.typicode.com", "dummy-key")

# 获取用户列表
users = client.get("/users")
for user in users[:2]: # 打印前两个
    print(user['name'])

# 创建一个新帖子
new_post = client.post("/posts", {
    "title": "My New Post",
    "body": "This is the content.",
    "userId": 1
})
print("创建的帖子:", new_post)

# 别忘了关闭
client.close()

解析 : 这个案例展示了如何利用Session和良好的错误处理来构建一个健壮、可复用的API客户端。


第二部分:httpx - 现代化的全能选手

httpx (pip install httpx) 是一个现代化的HTTP客户端,旨在成为requests的替代品,同时增加了许多激动人心的新特性。

2.1 同步与异步支持

这是httpx最大的亮点。你可以用几乎相同的API编写同步和异步代码。

python 复制代码
import httpx
import asyncio

# ---- 同步模式 (类似 requests) ----
def sync_example():
    response = httpx.get('https://httpbin.org/get')
    print(response.status_code)
    print(response.json()['url'])

sync_example()

# ---- 异步模式 (async/await) ----
async def async_example():
    async with httpx.AsyncClient() as client:
        response = await client.get('https://httpbin.org/get')
        print(response.status_code)
        print(response.json()['url'])

# 运行异步函数
asyncio.run(async_example())

优势: 异步I/O可以在等待网络响应时释放控制权,执行其他任务,极大地提高了I/O密集型应用(如爬虫、API聚合器)的并发性能。

2.2 HTTP/2 支持

httpx原生支持HTTP/2协议,可以更高效地复用连接,减少延迟。

python 复制代码
import httpx

# 默认情况下,如果服务器支持,httpx 会协商使用 HTTP/2
with httpx.Client(http2=True) as client:
    response = client.get('https://http2.golang.org')
    print(f"HTTP Version: {response.http_version}") # HTTP/2
2.3 实际案例:高效的异步爬虫
python 复制代码
​
1import httpx
2import asyncio
3from bs4 import BeautifulSoup
4
5# 我们要抓取的多个URL
6urls = [
7    'https://httpbin.org/delay/1',
8    'https://httpbin.org/delay/2',
9    'https://httpbin.org/delay/1',
10]
11
12async def fetch_title(client: httpx.AsyncClient, url: str) -> str:
13    """异步获取单个页面的标题"""
14    try:
15        response = await client.get(url, timeout=10)
16        response.raise_for_status()
17        
18        # 使用 BeautifulSoup 解析HTML
19        soup = BeautifulSoup(response.text, 'html.parser')
20        title_tag = soup.find('title')
21        title = title_tag.get_text(strip=True) if title_tag else "No Title"
22        
23        return f"{url}: {title}"
24    except Exception as e:
25        return f"{url}: Error - {e}"
26
27async def main():
28    # 创建一个共享的异步客户端
29    async with httpx.AsyncClient() as client:
30        # 使用 asyncio.gather 并发执行所有请求
31        tasks = [fetch_title(client, url) for url in urls]
32        results = await asyncio.gather(*tasks)
33        
34        for result in results:
35            print(result)
36
37# 运行主协程
38asyncio.run(main())

​

解析: 在同步版本中,抓取这三个URL至少需要1+2+1=4秒。而在异步版本中,由于是并发请求,总时间大约只有2秒多一点,性能提升显著。


第三部分:与 urllib 的对比

了解urllib有助于理解底层原理。

python 复制代码
# 使用 urllib 发送一个带参数和头部的GET请求
from urllib import request, parse

base_url = 'https://httpbin.org/get'
params = {'key': 'value'}
query_string = parse.urlencode(params)
full_url = f"{base_url}?{query_string}"

req = request.Request(
    full_url,
    headers={
        'User-Agent': 'MyApp/1.0'
    }
)

try:
    with request.urlopen(req, timeout=5) as response:
        data = response.read().decode('utf-8') # 必须手动解码
        print(data)
except Exception as e:
    print(f"Error: {e}")

对比:

  • 代码量 : urllib 需要更多样板代码。
  • 易用性 : requests/httpx 的API远胜一筹。
  • 功能 : requests/httpx 内置了JSON处理、会话管理、文件上传等高级功能。
  • 学习成本 : requests 几乎是零成本入门。

第四部分:最佳实践与陷阱
  1. 始终设置 timeout: 这是最重要的实践,防止程序挂起。
  2. 善用 Session/Client: 对于多次请求,复用连接能显著提升性能。
  3. 检查状态码 : 不要只依赖try-except,主动检查status_code或使用raise_for_status()
  4. 处理异常 : 捕获RequestException及其子类(ConnectionError, Timeout, HTTPError)。
  5. 管理连接 : 使用with语句确保SessionClient被正确关闭。
  6. 考虑异步 : 当需要高并发时(如爬取大量页面),httpx的异步模式是更好的选择。
  7. 安全: 不要在代码中硬编码敏感信息(如API密钥)。使用环境变量或配置文件。
结语

requests重新定义了Python的HTTP体验,而httpx则在此基础上引领我们走向异步和HTTP/2的未来。

通过本篇博客的学习,你应该已经掌握了:

  • 如何使用requests进行各种HTTP操作,并构建健壮的客户端。
  • httpx的强大功能,特别是其异步和HTTP/2支持。
  • 如何根据项目需求选择合适的库。
  • 至关重要的性能和安全最佳实践。
相关推荐
xnian_1 小时前
高并发下锁管理器,单机与分布式版
java·开发语言
不染尘.1 小时前
背包问题BP
开发语言·c++·算法
华科大胡子1 小时前
爬虫对抗:ZLibrary反爬机制实战分析
python
程序员buddha1 小时前
Java面试八股文基础篇
java·开发语言·面试
进击的小头2 小时前
第17篇:卡尔曼滤波器之概率论初步
python·算法·概率论
是梦终空2 小时前
计算机毕业设计269—基于python+深度学习+YOLOV8的交通标志识别系统(源代码+数据库+报告)
python·深度学习·opencv·毕业设计·torch·课程设计·pyqt5
2401_874732532 小时前
基于C++的爬虫框架
开发语言·c++·算法
3GPP仿真实验室2 小时前
【MATLAB源码】THz ISAC:太赫兹通感一体化链路级仿真平台
开发语言·matlab
lly2024062 小时前
HTML5 测验
开发语言