
requests 库如何发起一次 HTTP 请求
requests 并不是直接操作 socket 的底层库,而是基于 urllib3 构建的高层封装。当你调用 requests.get("https://example.com") 时,实际流程是:构造请求对象 → 经过会话(Session)管理 → 交由 urllib3 的连接池处理 → 建立 TCP 连接(或复用已有连接)→ 发送 HTTP 报文 → 接收响应 → 解析成 Response 对象。
核心组件分工:Session、Adapter 与 urllib3
requests 的设计采用“策略模式”分离关注点:
- Session:维护 cookies、默认 headers、认证信息、连接池配置等,支持跨请求状态保持;
-
HTTPAdapter:负责将 requests 的抽象请求映射为 urllib3 的具体行为,默认使用
HTTPAdapter,可替换为自定义适配器(如支持 SOCKS 代理或 mock 响应); - urllib3.PoolManager:管理连接池(每个 host+port 一个池),自动复用 TCP 连接(Keep-Alive)、处理重试、超时、SSL 验证等。
从 Request 到 Response 的关键转换环节
真正发送前,requests 会把用户传入的参数逐步标准化:
- URL 自动拼接 base_url + path + params(
params转为 query string); - headers 合并默认头(如 User-Agent)和用户指定头,不区分大小写覆盖;
- data / json 参数被序列化并设置对应 Content-Type(json 会自动加
application/json); - auth 参数(如
HTTPBasicAuth)被编码为 Authorization header; - 最终生成一个
PreparedRequest对象,交由 Adapter.send() 执行。
响应解析与异常机制的关键逻辑
收到原始 HTTP 响应后,requests 不仅返回字节流,还做了大量隐式处理:
立即学习“Python免费学习笔记(深入)”;
- 根据
Content-Encoding自动解压(gzip/deflate); - 根据
Content-Type和响应体推测编码(fallback 到 ISO-8859-1),暴露为.text属性; -
.json()方法内部调用json.loads(r.content.decode(r.encoding)),失败抛出JSONDecodeError; - 网络错误(DNS 失败、连接拒绝)抛出
ConnectionError;超时抛出Timeout;4xx/5xx 默认不报错,需显式调用r.raise_for_status()触发HTTPError。
不复杂但容易忽略的底层细节
比如连接复用依赖于服务端返回 Connection: keep-alive 和 Keep-Alive header;默认最大连接数是 10(每个 host),可通过 pool_connections 和 pool_maxsize 调整;SSL 验证开启时,会校验证书链和域名匹配,禁用验证(verify=False)会触发不安全警告。










