← 返回 Day 126 正文

Day 126 · 图解

Day 126 — Requests 深入:图解

1. Session 与独立请求对比

┌──────────────────────────────────────────────────────────────┐
│              独立请求 vs Session 会话                         │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  独立请求 (无状态)                                            │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐               │
│  │ 请求 1   │───▶│ 请求 2   │───▶│ 请求 3   │               │
│  │ 无Cookie │    │ 无Cookie │    │ 无Cookie │               │
│  └──────────┘    └──────────┘    └──────────┘               │
│       │               │               │                      │
│       ▼               ▼               ▼                      │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐               │
│  │ TCP 握手  │    │ TCP 握手  │    │ TCP 握手  │               │
│  │ TLS 握手  │    │ TLS 握手  │    │ TLS 握手  │               │
│  │ 发送请求  │    │ 发送请求  │    │ 发送请求  │               │
│  └──────────┘    └──────────┘    └──────────┘               │
│                                                              │
│  Session (有状态)                                            │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ requests.Session                                      │   │
│  │                                                      │   │
│  │  ┌──────────┐    ┌──────────┐    ┌──────────┐       │   │
│  │  │ 请求 1   │───▶│ 请求 2   │───▶│ 请求 3   │       │   │
│  │  │ 自动管理 │    │ 自动管理 │    │ 自动管理 │       │   │
│  │  │ Cookie   │    │ Cookie   │    │ Cookie   │       │   │
│  │  └──────────┘    └──────────┘    └──────────┘       │   │
│  │       │               │               │              │   │
│  │       ▼               ▼               ▼              │   │
│  │  ┌──────────┐    ┌──────────┐    ┌──────────┐       │   │
│  │  │ TCP 握手  │    │ 复用连接  │    │ 复用连接  │       │   │
│  │  │ TLS 握手  │    │          │    │          │       │   │
│  │  └──────────┘    └──────────┘    └──────────┘       │   │
│  │                                                      │   │
│  └──────────────────────────────────────────────────────┘   │
│                                                              │
│  性能对比:                                                    │
│  独立请求: ████████████████ (慢,每次建立新连接)               │
│  Session:  ████████ (快,复用连接 + 自动管理状态)              │
│                                                              │
└──────────────────────────────────────────────────────────────┘

2. 重试策略流程

┌──────────────────────────────────────────────────────────────┐
│                    重试策略流程                                │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────┐                                                 │
│  │ 发送请求 │                                                 │
│  └────┬────┘                                                 │
│       │                                                      │
│       ▼                                                      │
│  ┌─────────┐     成功      ┌─────────┐                      │
│  │ 检查结果 │─────────────▶│ 返回响应 │                      │
│  └────┬────┘              └─────────┘                       │
│       │ 失败                                                 │
│       ▼                                                      │
│  ┌─────────┐     否        ┌─────────┐                      │
│  │ 在重试   │─────────────▶│ 抛出异常 │                      │
│  │ 列表中?  │              └─────────┘                       │
│  └────┬────┘                                                 │
│       │ 是                                                   │
│       ▼                                                      │
│  ┌─────────┐     是        ┌─────────┐                      │
│  │ 重试次数 │─────────────▶│ 抛出异常 │                      │
│  │ 用完了?  │              └─────────┘                       │
│  └────┬────┘                                                 │
│       │ 否                                                   │
│       ▼                                                      │
│  ┌─────────────────────────────────────┐                    │
│  │         计算退避时间                  │                    │
│  │  backoff_factor × (2 ^ (重试次数-1)) │                    │
│  │                                     │                    │
│  │  第1次: 0.5s                        │                    │
│  │  第2次: 1.0s                        │                    │
│  │  第3次: 2.0s                        │                    │
│  └─────────────────────────────────────┘                    │
│       │                                                      │
│       ▼                                                      │
│  ┌─────────┐                                                 │
│  │ 等待并   │                                                 │
│  │ 重新发送 │──────▶ 返回发送请求步骤                          │
│  └─────────┘                                                 │
│                                                              │
└──────────────────────────────────────────────────────────────┘

3. 连接池工作原理

┌──────────────────────────────────────────────────────────────┐
│                    连接池工作原理                              │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │                requests.Session                       │   │
│  │                                                      │   │
│  │  ┌─────────────────────────────────────────────┐    │   │
│  │  │           HTTPAdapter (连接适配器)           │    │   │
│  │  │                                             │    │   │
│  │  │  ┌──────────────────────────────────────┐  │    │   │
│  │  │  │         连接池 (Connection Pool)      │  │    │   │
│  │  │  │                                      │  │    │   │
│  │  │  │  ┌──────┐ ┌──────┐ ┌──────┐         │  │    │   │
│  │  │  │  │Conn 1│ │Conn 2│ │Conn 3│  ...     │  │    │   │
│  │  │  │  │  ✅  │ │  ✅  │ │  ✅  │         │  │    │   │
│  │  │  │  └──┬───┘ └──┬───┘ └──┬───┘         │  │    │   │
│  │  │  │     │        │        │              │  │    │   │
│  │  │  └─────┼────────┼────────┼──────────────┘  │    │   │
│  │  └────────┼────────┼────────┼─────────────────┘    │   │
│  └───────────┼────────┼────────┼──────────────────────┘   │
│              │        │        │                           │
│              ▼        ▼        ▼                           │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              目标服务器                                │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                              │
│  工作流程:                                                    │
│  1. 请求到达 → 检查连接池                                     │
│  2. 有空闲连接 → 复用连接 (跳过 TCP/TLS 握手)                 │
│  3. 无空闲连接 → 创建新连接 (如果未达上限)                     │
│  4. 请求完成 → 连接返回连接池 (而不是关闭)                     │
│                                                              │
└──────────────────────────────────────────────────────────────┘

4. Mermaid 流程图

graph TD A[创建 Session] --> B[配置请求头] B --> C[设置认证信息] C --> D[配置重试策略] D --> E{发送请求} E -->|成功| F[返回响应] E -->|失败| G{检查重试} G -->|在重试列表中| H{重试次数?} G -->|不在列表中| I[抛出异常] H -->|未达上限| J[计算退避时间] H -->|已达上限| I J --> K[等待退避时间] K --> E F --> L{检查状态码} L -->|成功 2xx| M[返回结果] L -->|重试状态码| G L -->|其他错误| N[抛出 HTTPError] M --> O[更新 Cookie] O --> P[返回最终响应]
graph TD
    A[创建 Session] --> B[配置请求头]
    B --> C[设置认证信息]
    C --> D[配置重试策略]

    D --> E{发送请求}
    E -->|成功| F[返回响应]
    E -->|失败| G{检查重试}

    G -->|在重试列表中| H{重试次数?}
    G -->|不在列表中| I[抛出异常]

    H -->|未达上限| J[计算退避时间]
    H -->|已达上限| I

    J --> K[等待退避时间]
    K --> E

    F --> L{检查状态码}
    L -->|成功 2xx| M[返回结果]
    L -->|重试状态码| G
    L -->|其他错误| N[抛出 HTTPError]

    M --> O[更新 Cookie]
    O --> P[返回最终响应]

5. 请求头伪装效果对比

┌──────────────────────────────────────────────────────────────┐
│              请求头伪装效果对比                                │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  ❌ 未伪装 (python-requests)                                 │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ GET /api/data HTTP/1.1                               │   │
│  │ Host: target-site.com                                │   │
│  │ User-Agent: python-requests/2.31.0                   │   │
│  │ Accept: */*                                          │   │
│  │ Accept-Encoding: gzip, deflate                       │   │
│  │ Connection: keep-alive                               │   │
│  └──────────────────────────────────────────────────────┘   │
│  结果: 🚫 被识别为爬虫,返回 403 Forbidden                    │
│                                                              │
│  ✅ 伪装后 (真实浏览器)                                       │
│  ┌──────────────────────────────────────────────────────┐   │
│  │ GET /api/data HTTP/1.1                               │   │
│  │ Host: target-site.com                                │   │
│  │ User-Agent: Mozilla/5.0 (Windows NT 10.0; ...)      │   │
│  │ Accept: text/html,application/xhtml+xml,...          │   │
│  │ Accept-Language: zh-CN,zh;q=0.9,en;q=0.8            │   │
│  │ Accept-Encoding: gzip, deflate, br                   │   │
│  │ Connection: keep-alive                               │   │
│  │ Upgrade-Insecure-Requests: 1                         │   │
│  │ Sec-Fetch-Dest: document                             │   │
│  │ Sec-Fetch-Mode: navigate                             │   │
│  │ Sec-Fetch-Site: none                                 │   │
│  │ Sec-Fetch-User: ?1                                   │   │
│  │ Sec-Ch-Ua: "Not_A Brand";v="8",...                  │   │
│  │ Sec-Ch-Ua-Mobile: ?0                                 │   │
│  │ Sec-Ch-Ua-Platform: "Windows"                        │   │
│  └──────────────────────────────────────────────────────┘   │
│  结果: ✅ 正常访问,返回 200 OK                               │
│                                                              │
└──────────────────────────────────────────────────────────────┘