Files
ocups-kafka/docs/技术方案.md
2026-01-15 21:20:57 +08:00

14 KiB
Raw Blame History

招聘数据增量采集与消息队列服务技术方案

1. 项目概述

1.1 需求背景

从八爪鱼API采集招聘数据筛选近7天发布的数据通过RabbitMQ消息队列提供数据消费接口支持消息级别TTL自动过期。

1.2 核心功能

  • 增量采集八爪鱼API招聘数据从后往前采集最新数据优先
  • 日期过滤(发布日期 + 采集时间均在7天内
  • RabbitMQ消息队列支持消息TTL7天自动过期
  • 容器启动自动开始采集
  • 提供REST API消费接口

2. 系统架构

┌─────────────────────────────────────────────────────────────────┐
│                         系统架构图                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────────┐  │
│  │  八爪鱼API   │───▶│  采集服务    │───▶│   日期过滤器     │  │
│  │  (数据源)    │    │ (从后往前)   │    │  (7天内数据)     │  │
│  └──────────────┘    └──────────────┘    └────────┬─────────┘  │
│                                                    │            │
│                                                    ▼            │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                    RabbitMQ 服务                          │  │
│  │  ┌─────────────────────────────────────────────────────┐ │  │
│  │  │  Queue: job_data                                    │ │  │
│  │  │  - 消息TTL: 7天 (604800000ms)                       │ │  │
│  │  │  - 过期消息自动删除                                  │ │  │
│  │  │  - 持久化存储                                        │ │  │
│  │  └─────────────────────────────────────────────────────┘ │  │
│  └──────────────────────────────────────────────────────────┘  │
│                                                    │            │
│                                                    ▼            │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │                    FastAPI 服务                           │  │
│  │  ┌─────────────────┐  ┌─────────────────────────────┐    │  │
│  │  │ GET /consume    │  │ GET /status                 │    │  │
│  │  │ (消费数据)      │  │ (采集状态/进度)             │    │  │
│  │  └─────────────────┘  └─────────────────────────────┘    │  │
│  └──────────────────────────────────────────────────────────┘  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

3. 技术选型

组件 技术方案 版本 说明
运行环境 Python 3.11+ 主开发语言
HTTP客户端 httpx 0.27+ 异步HTTP请求
消息队列 RabbitMQ 3.12+ 支持消息级别TTL
MQ客户端 pika 1.3+ Python RabbitMQ SDK
API框架 FastAPI 0.109+ REST接口
容器编排 Docker Compose 2.0+ 服务部署
数据存储 SQLite 内置 存储采集进度

4. 项目结构

job_crawler/
├── app/                        # 应用代码
│   ├── api/                    # API路由层
│   │   ├── __init__.py
│   │   └── routes.py           # 路由定义
│   ├── core/                   # 核心配置
│   │   ├── __init__.py
│   │   ├── config.py           # 配置管理
│   │   └── logging.py          # 日志配置
│   ├── models/                 # 数据模型
│   │   ├── __init__.py
│   │   ├── job.py              # 招聘数据模型
│   │   ├── progress.py         # 进度模型
│   │   └── response.py         # 响应模型
│   ├── services/               # 业务服务层
│   │   ├── __init__.py
│   │   ├── api_client.py       # 八爪鱼API客户端
│   │   ├── crawler.py          # 采集核心逻辑
│   │   ├── rabbitmq_service.py # RabbitMQ服务
│   │   └── progress_store.py   # 进度存储
│   ├── utils/                  # 工具函数
│   │   ├── __init__.py
│   │   └── date_parser.py      # 日期解析
│   ├── __init__.py
│   └── main.py                 # 应用入口
├── config/                     # 配置文件
│   ├── config.yml              # 运行配置
│   └── config.yml.docker       # Docker配置模板
├── docker-compose.yml          # 容器编排
├── Dockerfile                  # 应用镜像构建
├── deploy.sh                   # 部署脚本(Linux)
├── deploy.bat                  # 部署脚本(Windows)
├── requirements.txt            # Python依赖
└── README.md                   # 使用说明

5. 核心模块设计

5.1 增量采集模块

采集策略(从后往前)

# 增量采集流程
1. 获取数据总数 total
2. 读取上次采集的起始位置 last_start_offset
3. 计算本次采集范围:
   - start_offset = total - batch_size (从最新数据开始)
   - end_offset = last_start_offset (截止到上次位置)
4. 循环采集: offset  start_offset 递减到 end_offset
5. 每批数据过滤后立即发送到RabbitMQ
6. 采集完成后保存 last_start_offset = 本次起始位置

进度持久化

使用SQLite存储采集进度

CREATE TABLE crawl_progress (
    task_id TEXT PRIMARY KEY,
    last_start_offset INTEGER,  -- 上次采集的起始位置
    total INTEGER,
    last_update TIMESTAMP,
    status TEXT,
    filtered_count INTEGER,
    produced_count INTEGER
);

5.2 日期过滤模块

aae397 字段格式解析

原始值 解析规则 示例结果
"今天" 当前日期 2026-01-15
"1月13日" 当年+月日 2026-01-13
"1月9日" 当年+月日 2026-01-09

过滤逻辑

def is_within_days(aae397: str, collect_time: str, days: int = 7) -> bool:
    """
    判断数据是否在指定天数内
    条件:发布日期 AND 采集时间 都在N天内
    """
    today = datetime.now().date()
    cutoff_date = today - timedelta(days=days)
    
    publish_date = parse_aae397(aae397)
    collect_date = parse_collect_time(collect_time)
    
    return publish_date >= cutoff_date and collect_date >= cutoff_date

5.3 RabbitMQ服务模块

消息TTL机制

# 队列声明时设置消息TTL
channel.queue_declare(
    queue='job_data',
    durable=True,
    arguments={
        'x-message-ttl': 604800000  # 7天(毫秒)
    }
)

# 发送消息时也设置TTL双重保障
channel.basic_publish(
    exchange='',
    routing_key='job_data',
    body=message,
    properties=pika.BasicProperties(
        delivery_mode=2,  # 持久化
        expiration='604800000'  # 7天
    )
)

优势

  • 消息级别TTL精确控制每条消息的过期时间
  • 过期消息自动删除,无需手动清理
  • 队列中始终保持最近7天的有效数据

5.4 REST API接口

接口 方法 说明
/consume GET 消费队列数据支持batch_size参数
/queue/size GET 获取队列消息数量
/status GET 查看采集进度和状态
/tasks GET 获取任务列表
/crawl/start POST 手动触发采集任务
/crawl/stop POST 停止采集任务

接口详情

GET /consume

// Request
GET /consume?batch_size=10

// Response
{
  "code": 0,
  "data": [
    {
      "_id": "uuid",
      "_task_id": "00f3b445-...",
      "_crawl_time": "2026-01-15T10:30:00",
      "Std_class": "机动车司机/驾驶",
      "aca112": "保底1万+五险+港内A2驾驶员",
      "AAB004": "青岛唐盛物流有限公司",
      "acb241": "1-1.5万",
      "aab302": "青岛黄岛区",
      "aae397": "1月13日",
      "Collect_time": "2026-01-15",
      ...
    }
  ],
  "count": 10
}

GET /status

{
  "code": 0,
  "data": {
    "tasks": [
      {
        "task_id": "00f3b445-...",
        "task_name": "青岛招聘数据",
        "total": 270000,
        "last_start_offset": 269900,
        "status": "completed",
        "filtered_count": 15000,
        "produced_count": 15000,
        "is_running": false
      }
    ],
    "queue_size": 12345,
    "running_count": 0
  }
}

6. 数据模型

6.1 原始数据保留

数据采集后保留原始字段名,仅添加元数据:

字段 说明
_id 唯一标识(UUID)
_task_id 任务ID
_crawl_time 入库时间
其他字段 保留原始API返回的所有字段

6.2 RabbitMQ消息格式

{
  "_id": "uuid",
  "_task_id": "00f3b445-d8ec-44e8-88b2-4b971a228b1e",
  "_crawl_time": "2026-01-15T10:30:00",
  "Std_class": "机动车司机/驾驶",
  "aca112": "保底1万+五险+港内A2驾驶员",
  "AAB004": "青岛唐盛物流有限公司",
  "AAB019": "民营",
  "acb241": "1-1.5万",
  "aab302": "青岛黄岛区",
  "AAE006": "青岛市黄岛区...",
  "aae397": "1月13日",
  "Collect_time": "2026-01-15",
  "ACE760": "https://www.zhaopin.com/...",
  "acb22a": "岗位职责...",
  "Experience": "5-10年",
  "aac011": "学历不限",
  "acb240": "1人",
  "AAB022": "交通/运输/物流",
  "Num_employers": "20-99人",
  "AAE004": "张先生/HR",
  "AAB092": "公司简介..."
}

7. 配置说明

配置文件 config/config.yml

# 应用配置
app:
  name: job-crawler
  version: 1.0.0
  debug: false

# 八爪鱼API配置
api:
  base_url: https://openapi.bazhuayu.com
  username: "your_username"
  password: "your_password"
  batch_size: 100
  # 多任务配置
  tasks:
    - id: "00f3b445-d8ec-44e8-88b2-4b971a228b1e"
      name: "青岛招聘数据"
      enabled: true
    - id: "task-id-2"
      name: "任务2"
      enabled: false

# RabbitMQ配置
rabbitmq:
  host: rabbitmq           # Docker内部服务名
  port: 5672
  username: guest
  password: guest
  queue: job_data
  message_ttl: 604800000   # 消息过期时间7天(毫秒)

# 采集配置
crawler:
  filter_days: 7           # 数据有效期(天)
  max_expired_batches: 3   # 连续过期批次阈值
  max_workers: 5           # 最大并行任务数
  auto_start: true         # 容器启动时自动开始采集

# 数据库配置
database:
  path: data/crawl_progress.db

8. 部署流程

8.1 Docker Compose 一键部署

# 1. 配置
cd job_crawler
cp config/config.yml.docker config/config.yml
# 编辑 config/config.yml 填入账号密码

# 2. 构建镜像
./deploy.sh build

# 3. 启动服务
./deploy.sh up

# 4. 查看日志
./deploy.sh logs

# 5. 查看状态
./deploy.sh status

8.2 部署脚本命令

命令 说明
./deploy.sh build 构建镜像
./deploy.sh up 启动服务
./deploy.sh down 停止服务
./deploy.sh restart 重启应用
./deploy.sh logs 查看应用日志
./deploy.sh status 查看服务状态
./deploy.sh reset 清理数据卷并重启

8.3 服务端口

服务 端口 说明
FastAPI 8000 HTTP API
RabbitMQ 5672 AMQP协议
RabbitMQ 15672 管理界面

8.4 访问地址


9. 数据流向

八爪鱼API → 采集服务(过滤7天内数据) → RabbitMQ(TTL=7天) → 第三方消费
                                            ↓
                                      过期自动删除

10. Token自动刷新机制

系统实现了Token自动管理

  1. 首次请求时自动获取Token
  2. Token缓存在内存中
  3. 请求前检查Token有效期提前5分钟刷新
  4. 遇到401错误自动重新获取Token

11. 异常处理

异常场景 处理策略
API请求失败 重试3次指数退避
Token过期 自动刷新Token
RabbitMQ连接失败 自动重连
日期解析失败 记录日志,跳过该条数据

12. 快速启动

# 1. 配置
cd job_crawler
cp config/config.yml.docker config/config.yml
# 编辑 config/config.yml 填入账号密码

# 2. 一键启动
./deploy.sh build
./deploy.sh up

# 3. 查看采集日志
./deploy.sh logs

# 4. 消费数据
curl http://localhost:8000/consume?batch_size=10

# 5. 查看队列大小
curl http://localhost:8000/queue/size