← 返回 Day 77 正文

Day 77 · 图解

Day 077 — 图解:请求调度与数据管道

1. Scrapy 数据流全景图

                        ┌──────────────────────────────────────┐
                        │           Spider                     │
                        │   (解析响应,产出 Request 和 Item)      │
                        └──────┬──────────────┬────────────────┘
                               │              │
                    Request    │              │  Item
                               ▼              ▼
                   ┌───────────────┐    ┌───────────────┐
                   │   Scheduler   │    │   Pipeline    │
                   │   (调度器)     │    │   (管道)      │
                   └───────┬───────┘    └───────┬───────┘
                           │                    │
              ┌────────────┤                    │
              │            │                    │
              ▼            ▼                    ▼
     ┌─────────────┐ ┌──────────┐      ┌──────────────┐
     │ DupeFilter  │ │  Queue   │      │  数据处理链   │
     │ (去重过滤)   │ │ (请求队列)│      │  清洗→验证→存储│
     └─────────────┘ └──────────┘      └──────────────┘
              │            │
              └────────────┤
                           ▼
                   ┌───────────────┐
                   │   Downloader  │
                   │   (下载器)     │
                   └───────┬───────┘
                           │
                           ▼
                   ┌───────────────┐
                   │  Middleware   │
                   │  (中间件)      │
                   └───────────────┘

2. 调度器内部机制

┌─────────────────────────────────────────────────────────────┐
│                    Scrapy Scheduler                          │
│                                                             │
│  新请求进入                                                  │
│       │                                                     │
│       ▼                                                     │
│  ┌─────────────┐                                            │
│  │ DupeFilter  │── 指纹已存在 ──→ ⛔ 丢弃                   │
│  │ (指纹检查)   │                                            │
│  └──────┬──────┘                                            │
│         │ 指纹不存在                                         │
│         ▼                                                   │
│  ┌─────────────┐                                            │
│  │ Priority    │                                            │
│  │ Queue       │  priority=10  ┐                             │
│  │ (优先级堆)   │  priority=5   ├→ 出队时取最高优先级         │
│  │             │  priority=0   ┘                             │
│  └──────┬──────┘                                            │
│         │                                                   │
│         ▼                                                   │
│    下一个待爬取请求                                            │
└─────────────────────────────────────────────────────────────┘

3. Pipeline 执行流程

Item 产出
    │
    ▼
┌─────────────────────────────────────────────────────────┐
│ Pipeline 100: CleanPipeline                             │
│ • 去除空白字符                                           │
│ • 标准化价格格式                                         │
│ • 添加时间戳                                             │
│ 返回处理后的 Item ──→ ✅                                   │
│ 无效数据 ──→ raise DropItem ──→ ⛔ 丢弃                  │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│ Pipeline 200: ValidatePipeline                           │
│ • 必填字段检查                                           │
│ • 类型校验                                               │
│ • 业务规则校验                                           │
│ 返回处理后的 Item ──→ ✅                                   │
│ 不合规数据 ──→ raise DropItem ──→ ⛔ 丢弃                  │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│ Pipeline 300: StorePipeline                              │
│ • 写入数据库                                             │
│ • 或导出为文件                                           │
│ 返回处理后的 Item ──→ ✅                                   │
└─────────────────────────────────────────────────────────┘

4. 去重指纹生成流程

Request(url, method, body)
    │
    ▼
┌──────────────────────────────┐
│  1. 提取 URL 参数             │
│  url = "https://a.com/p=1&t=2"│
│  params = {p: [1], t: [2]}   │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│  2. 移除忽略参数(可选)       │
│  remove(params, 't')         │
│  params = {p: [1]}           │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│  3. 排序并重建 URL            │
│  clean_url = "https://a.com/p=1"│
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│  4. 生成哈希指纹             │
│  fp = sha1(clean_url + method + body)│
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────┐
│  5. 检查指纹集合              │
│  fp in seen?                  │
│  ├─ No  → 允许,记录指纹      │
│  └─ Yes → 过滤掉              │
└──────────────────────────────┘

5. 断点续爬机制

第一次运行                          中断后恢复
    │                                   │
    ▼                                   ▼
┌─────────────┐                   ┌─────────────┐
│ 开始爬取     │                   │ 读取 JOBDIR  │
│             │                   │             │
│ 处理 50%    │     进程崩溃       │ 恢复队列状态 │
│    │        │ ─────────────→    │ 恢复去重集合 │
│    ▼        │                   │    │        │
│ 保存状态    │                   │    ▼        │
│ 到 JOBDIR   │                   │ 继续爬取     │
│             │                   │ 剩余 50%    │
└─────────────┘                   └─────────────┘

JOBDIR 保存的内容:
├── queue/          # 请求队列(未处理的请求)
├── dupefilter/     # 去重指纹集合
└── requests.queue  # 调度器状态