175 lines
6.7 KiB
Markdown
175 lines
6.7 KiB
Markdown
# JobData - 招聘数据采集与统计分析平台
|
||
|
||
## 变更记录 (Changelog)
|
||
|
||
| 版本 | 日期 | 说明 |
|
||
|------|------|------|
|
||
| 初始化 | 2026-03-20 | 首次生成架构文档,覆盖全部四个核心模块 |
|
||
|
||
---
|
||
|
||
## 项目愿景
|
||
|
||
JobData 是一个面向招聘市场的全栈数据采集与分析平台。系统从三大主流招聘平台(Boss 直聘、前程无忧、智联招聘)自动抓取职位与公司数据,统一存储到 ClickHouse 列式数据库,并通过 FastAPI 后端 + Vue3 前端提供数据查看、定向清洗、统计分析等能力。ECS 弹性实例管理模块支持在阿里云上按需批量启停爬虫节点。
|
||
|
||
---
|
||
|
||
## 架构总览
|
||
|
||
```
|
||
[招聘平台] [爬虫层] [后端 API] [数据库]
|
||
Boss直聘 ──► jobs_spider/boss/ ──► ┌── MySQL
|
||
前程无忧 ──► jobs_spider/qcwy/ ──► app (FastAPI) ──► └── ClickHouse
|
||
智联招聘 ──► jobs_spider/zhilian/ ──►
|
||
▲
|
||
│
|
||
web (Vue3) ────────┘
|
||
(前端页面)
|
||
|
||
ecs_full_pipeline.py ──► 阿里云 ECS ──► 批量启动爬虫节点
|
||
```
|
||
|
||
**核心技术栈**
|
||
|
||
| 层次 | 技术 |
|
||
|------|------|
|
||
| 后端 | Python 3.13, FastAPI 0.111, Tortoise-ORM 0.23, APScheduler |
|
||
| 数据库(业务) | MySQL(用户/权限/审计/关键词/Token) |
|
||
| 数据库(采集) | ClickHouse(职位/公司 JSON 原始数据 + 分析视图) |
|
||
| 爬虫 | requests / httpx / Playwright(Python 脚本) |
|
||
| 前端 | Vue 3.3, Vite 4, Naive UI, Pinia, ECharts |
|
||
| 基础设施 | 阿里云 ECS(按量抢占实例),APScheduler 定时任务 |
|
||
|
||
---
|
||
|
||
## 模块结构图
|
||
|
||
```mermaid
|
||
graph TD
|
||
ROOT["(根) JobData"] --> APP["app - FastAPI 后端"]
|
||
ROOT --> WEB["web - Vue3 前端"]
|
||
ROOT --> SPIDER["jobs_spider - 平台爬虫"]
|
||
ROOT --> ECS["ecs_full_pipeline.py - ECS 批量部署"]
|
||
|
||
APP --> APP_API["app/api - 路由层"]
|
||
APP --> APP_SVC["app/services - 业务逻辑"]
|
||
APP --> APP_CORE["app/core - 框架核心"]
|
||
APP --> APP_MODELS["app/models - ORM 模型"]
|
||
APP --> APP_REPO["app/repositories - 数据仓库"]
|
||
|
||
SPIDER --> SP_BOSS["jobs_spider/boss"]
|
||
SPIDER --> SP_QCWY["jobs_spider/qcwy"]
|
||
SPIDER --> SP_ZL["jobs_spider/zhilian"]
|
||
|
||
click APP "./app/AGENTS.md" "查看 app 模块文档"
|
||
click WEB "./web/AGENTS.md" "查看 web 模块文档"
|
||
click SPIDER "./jobs_spider/AGENTS.md" "查看 jobs_spider 模块文档"
|
||
```
|
||
|
||
---
|
||
|
||
## 模块索引
|
||
|
||
| 模块路径 | 语言 | 职责简述 |
|
||
|----------|------|----------|
|
||
| `app/` | Python | FastAPI 后端,提供 REST API、权限管理、定时任务、数据入库与分析 |
|
||
| `web/` | Vue3/JS | 前端管理界面,数据展示、关键词管理、代理管理、数据清洗操作 |
|
||
| `jobs_spider/` | Python | 三大平台的爬虫脚本,独立运行,结果通过 HTTP 推送到后端 |
|
||
| `ecs_full_pipeline.py` | Python | 阿里云 ECS 实例批量创建/销毁/命令下发全流程脚本 |
|
||
| `reclean_qcwy_jobs.py` | Python | 前程无忧数据重清洗独立脚本 |
|
||
|
||
---
|
||
|
||
## 运行与开发
|
||
|
||
### 后端启动
|
||
|
||
```bash
|
||
# 安装依赖(pipenv)
|
||
pipenv install
|
||
|
||
# 开发模式(默认端口 9999,20 个 worker)
|
||
python run.py
|
||
|
||
# 环境变量覆盖
|
||
APP_HOST=0.0.0.0 APP_PORT=9999 UVICORN_WORKERS=4 python run.py
|
||
```
|
||
|
||
**关键环境变量**
|
||
|
||
| 变量 | 默认值 | 说明 |
|
||
|------|--------|------|
|
||
| `APP_HOST` | `0.0.0.0` | 监听地址 |
|
||
| `APP_PORT` | `9999` | 监听端口 |
|
||
| `UVICORN_WORKERS` | `20` | Worker 数量 |
|
||
| `CLICKHOUSE_HOST` | `121.4.126.241` | ClickHouse 地址(需修改为实际地址) |
|
||
| `CLICKHOUSE_USER` / `CLICKHOUSE_PASS` | 见 config.py | ClickHouse 认证 |
|
||
| `SMTP_HOST` / `SMTP_USER` / `SMTP_PASS` | 见 config.py | 邮件告警配置 |
|
||
| `REPORT_ENDPOINT` | 空 | 统计结果 Webhook 上报地址 |
|
||
| `RUN_MIGRATIONS_ON_STARTUP` | `True` | 是否启动时自动迁移 |
|
||
| `INITIALIZE_SEED_DATA_ON_STARTUP` | `True` | 是否启动时初始化种子数据 |
|
||
|
||
> 安全警告:`config.py` 中 `SECRET_KEY`、数据库连接串、SMTP 密码均为硬编码默认值,生产环境必须通过环境变量覆盖。
|
||
|
||
### 前端启动
|
||
|
||
```bash
|
||
cd web
|
||
pnpm install
|
||
pnpm dev # 开发模式,默认 http://localhost:5173
|
||
pnpm build # 构建产物到 web/dist
|
||
```
|
||
|
||
### ECS 批量爬虫部署
|
||
|
||
```bash
|
||
# 需配置阿里云凭据(环境变量或 ~/.alibabacloud/credentials)
|
||
python ecs_full_pipeline.py
|
||
```
|
||
|
||
---
|
||
|
||
## 定时任务
|
||
|
||
APScheduler 在应用启动时注册以下任务(`app/core/scheduler.py`):
|
||
|
||
| 任务 ID | 频率 | 职责 |
|
||
|---------|------|------|
|
||
| `stats_job` | 每 6 小时 | 统计 ClickHouse 各表总量并通过邮件/Webhook 上报 |
|
||
| `ecs_full_pipeline` | 每 6 小时 | 调用 `ecs_full_pipeline.py` 批量刷新爬虫节点 |
|
||
| `ip_alert_job` | 每 10 分钟 | 检查 IP 上报异常并告警 |
|
||
| `company_cleaning_job` | 每 5 分钟 | 自动清洗待处理公司数据(collect 50 + process 30) |
|
||
| `daily_cleanup_job` | 每天 00:05 | 清理历史任务运行记录 |
|
||
|
||
所有任务通过分布式文件锁(或可选 Redis 锁)保证多 Worker 下只执行一次。
|
||
|
||
---
|
||
|
||
## 测试策略
|
||
|
||
- 当前代码库**无自动化测试文件**(缺口:单元测试、集成测试均缺失)。
|
||
- 推荐补充:
|
||
1. `app/services/` 的 service 层单元测试(使用 `pytest` + `anyio`)
|
||
2. `app/api/v1/` 的 API 集成测试(使用 `httpx.AsyncClient`)
|
||
3. `jobs_spider/` 的数据解析函数单元测试
|
||
|
||
---
|
||
|
||
## 编码规范
|
||
|
||
- Python:使用 `ruff`(已在 Pipfile 中),格式化用 `black`,排序用 `isort`。
|
||
- 前端:ESLint(`@zclzone` + `@unocss` 规则集),`prettier` 格式化。
|
||
- 类型:后端强制 `pydantic` Schema 做入参校验;前端以 JS 为主(未启用严格 TS)。
|
||
- 日志:后端统一使用 `loguru`,结构化字段 `logger.info(...)` 方式输出。
|
||
|
||
---
|
||
|
||
## AI 使用指引
|
||
|
||
- 修改爬虫逻辑时,重点关注反爬机制:`SmartIPManager`、`IPAnomalyDetector` 在 `jobs_spider/boss/boos_api.py` 中实现,随机延迟至少 10 秒。
|
||
- 新增 API 路由后需同步在 `app/api/v1/__init__.py` 注册,并执行 `api_controller.refresh_api()` 更新权限表。
|
||
- ClickHouse 表结构变更在 `app/core/clickhouse_init.py` 中维护,**不走 Aerich 迁移**。
|
||
- MySQL 模型变更走 Aerich(`aerich migrate && aerich upgrade`)。
|
||
- 前端新增页面需要在 `web/src/views/{模块}/route.js` 和后端 `init_menus()` 中同步注册菜单。
|
||
- `config.py` 中已硬编码真实 MySQL/ClickHouse 连接串和 SMTP 凭据,**提交代码前务必确认不泄露敏感信息**。
|