施工中...

文章背景图

如何使用Httpx设计一个简易异步爬虫引擎

2026-03-08
5
-
- 分钟
|

简易异步爬虫引擎的设计,主要分为核心功能模块和架构设计两个部分:

一、 核心功能模块设计

引擎包含以下七个核心组件:

1. 调度器 (Scheduler)

  • 需要一个容器(优先级队列)来管理待抓取的 URL。

  • 需要支持 URL 去重功能,避免重复抓取浪费资源。

  • 需要能判断优先级,比如详情页优先级高于列表页。

  • 支持按域名分组调度,避免同一域名请求过于集中。

  • 支持断点续爬,爬取进度持久化存储。

2. 异步下载器 (Downloader)

  • 引擎的"手脚"。基于 httpx 封装(或者aiohttp)。

  • 并发控制,限制同时请求的数量,防止把目标服务器搞崩或者被封IP。

  • 需要设计重试机制,遇到网络波动自动重试。

  • 速率限制,支持单域名请求间隔控制。

  • 随机延迟,模拟人类行为,降低被封风险。

3. 解析器 (Parser)

  • 引擎的"眼睛"。负责从 HTML/XML/JSON/TEXT 中提取数据。

  • 设计成可插拔的形式,不同的网站配置不同的解析规则(XPath 或 CSS Selector)。

  • 支持自动编码检测与转换。

4. 数据管道 (Pipeline)

  • 设计一个出口接口,支持保存为 JSON、CSV 或者存入数据库,把存储逻辑和爬取逻辑解耦。

  • 支持异步写入,不阻塞爬取流程。

  • 数据去重机制,避免重复存储。

5. 异常与日志监控 (Monitor)

  • 引擎需要有"黑匣子"日志记录,记录请求耗时、成功失败率、错误详情。

  • 实时统计面板,展示爬取进度、成功率、剩余任务数等。

  • 错误告警机制,异常率超过阈值时发出警告。

6. 中间件系统 (Middleware) —— 新增

  • 请求中间件: 请求发出前进行处理。

  1. 自动添加/轮换 User-Agent

  2. Cookies 管理

  3. Referer 自动填充

  4. 请求签名(应对反爬)

  • 响应中间件: 响应返回后进行处理。

  1. 自动解码

  2. 异常状态码处理

  • 异常中间件: 统一异常处理入口。

7. 代理管理器 (ProxyManager)

  • 代理池管理,支持从文件/API/数据库加载代理。

  • 代理轮换策略(随机/顺序/权重)。

  • 失效代理检测与自动剔除。

  • 支持认证代理。


二、 架构设计思路

采用 生产者-消费者模型 来设计整体的数据流向:

┌─────────────────────────────────────────────────────────────────┐
│                          配置管理层                              │
│              settings.py / YAML / 环境变量                       │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                          引擎核心 (Engine)                       │
├────────────┬────────────┬────────────┬────────────┬─────────────┤
│   调度器    │   下载器    │   解析器    │   管道     │    监控    │
│ Scheduler  │ Downloader │   Parser   │  Pipeline  │   Monitor   │
└─────┬──────┴─────┬──────┴─────┬──────┴─────┬──────┴──────┬──────┘
      │            │            │            │             │
      ▼            ▼            ▼            ▼             ▼
┌─────────────────────────────────────────────────────────────────┐
│                        中间件层 (Middleware)                     │
│    请求中间件  │  响应中间件  │  异常中间件  │  Spider中间件       │
└─────────────────────────────────────────────────────────────────┘
      │
      ▼
┌─────────────────────────────────────────────────────────────────┐
│                       代理管理器 (ProxyManager)                  │
└─────────────────────────────────────────────────────────────────┘

数据流转流程

1. 入口:

你将起始 URL 放入调度器队列。

2. 循环引擎:

这是异步的核心。引擎不断从调度器取出 URL,分发给空闲的下载器协程。下载完成后,将结果传给解析器。

3. 中间件处理:

  • 请求发出前,经过请求中间件处理(添加 UA、Cookies 等)。

  • 响应返回后,经过响应中间件处理(解码、状态检查)。

4. 数据流转:

解析器提取数据后,做两件事:

  • 将新的 URL 推回调度器队列(生产者)。

  • 将有效数据推送到数据管道进行保存。

5. 异步处理:

利用 Python 的 httpx 库,让下载器在等待网络 I/O 时挂起,转而去处理其他请求,这样能极大提高并发效率。


三、 异常处理策略

异常类型

HTTP 状态码

处理策略

网络超时

--

重试(最多3次)+ 指数退避

客户端错误

4xx

记录日志并跳过,不重试

服务端错误

5xx

重试 + 降低优先级

反爬封禁

403/429

切换代理 / 增加延迟 / 暂停爬取

重定向过多

3xx

跟随重定向,限制最大次数

重试机制详解

第1次重试:等待 1 秒
第2次重试:等待 2 秒
第3次重试:等待 4 秒
超过3次:标记为失败,记录日志

四、 配置管理

建议使用 dataclass 或 YAML 文件管理配置:

@dataclass
class Settings:
    CONCURRENCY: int = 10              # 并发数
    REQUEST_DELAY: float = 0.5         # 请求间隔(秒)
    RANDOM_DELAY: tuple = (0.1, 0.5)   # 随机延迟范围
    TIMEOUT: int = 30                  # 超时时间
    MAX_RETRIES: int = 3               # 最大重试次数
    USER_AGENT: str = "..."            # 默认 UA
    PROXY_ENABLED: bool = False        # 是否启用代理
    LOG_LEVEL: str = "INFO"            # 日志级别

五、 目录结构建议

spider_engine/
├── init.py
├── engine.py           # 引擎核心
├── scheduler.py        # 调度器
├── downloader.py       # 下载器
├── parser.py           # 解析器基类
├── pipeline.py         # 数据管道
├── monitor.py          # 监控模块
├── middleware/         # 中间件
│   ├── init.py
│   ├── base.py         # 中间件基类
│   ├── request.py      # 请求中间件
│   └── response.py     # 响应中间件
├── proxy/              # 代理管理
│   ├── init.py
│   └── manager.py
├── utils/              # 工具函数
│   ├── init.py
│   └── helpers.py
└── settings.py         # 配置文件

评论交流

文章目录