198 lines
8.6 KiB
Markdown
198 lines
8.6 KiB
Markdown
[根目录](../CLAUDE.md) > **app**
|
||
|
||
# app - FastAPI 后端模块
|
||
|
||
## 模块职责
|
||
|
||
提供 JobData 平台的 REST API 服务,包含:用户/角色/权限/菜单/部门管理(RBAC),招聘数据入库、查询、清洗与分析,Token 与代理 IP 管理,定时任务调度,以及审计日志记录。
|
||
|
||
---
|
||
|
||
## 入口与启动
|
||
|
||
| 文件 | 说明 |
|
||
|------|------|
|
||
| `run.py`(根目录) | `uvicorn` 启动入口,读取 `APP_HOST`/`APP_PORT`/`UVICORN_WORKERS` 环境变量 |
|
||
| `app/__init__.py` | FastAPI 应用工厂 `create_app()`,注册中间件、异常处理器、路由,以及 lifespan 钩子 |
|
||
| `app/core/init_app.py` | lifespan 内部逻辑:DB 迁移、种子数据、ClickHouse 初始化 |
|
||
| `app/core/scheduler.py` | APScheduler 启动与任务注册 |
|
||
|
||
### 启动顺序
|
||
|
||
1. Tortoise-ORM 连接 MySQL,生成 schema
|
||
2. 按环境变量执行数据库迁移(Aerich)
|
||
3. 初始化种子数据(超级管理员、菜单、API、角色)
|
||
4. 初始化 ClickHouse 表/视图(可选)
|
||
5. APScheduler 启动定时任务
|
||
6. FastAPI 开始接受请求
|
||
|
||
---
|
||
|
||
## 对外接口
|
||
|
||
API 前缀:`/api/v1`,完整路由注册见 `app/api/v1/__init__.py`。
|
||
|
||
| 路由前缀 | 标签 | 权限 | 说明 |
|
||
|----------|------|------|------|
|
||
| `/base` | 基础模块 | 无 | 登录、获取用户信息、菜单树 |
|
||
| `/user` | 用户管理 | DependPermission | 用户 CRUD |
|
||
| `/role` | 角色管理 | DependPermission | 角色 CRUD、菜单/API 分配 |
|
||
| `/menu` | 菜单管理 | DependPermission | 菜单树 CRUD |
|
||
| `/api` | API 管理 | DependPermission | 接口注册与权限管理 |
|
||
| `/dept` | 部门管理 | DependPermission | 部门树 CRUD |
|
||
| `/auditlog` | 审计日志 | DependPermission | 操作日志查询 |
|
||
| `/job` & `/universal` | 数据入库/通用数据接口 | 无鉴权(内部调用) | 职位/公司数据批量入库 |
|
||
| `/token` | Token 管理 | 无鉴权 | Boss Token CRUD |
|
||
| `/proxy` | 代理 IP 管理 | DependPermission | 代理池管理 |
|
||
| `/stats` | 数据统计 | 无 | 各平台数据量统计 |
|
||
| `/pipeline` | 流水线 | 无 | 触发 ECS pipeline |
|
||
| `/keyword` | 关键词管理 | 无 | 爬虫关键词(城市+职位)管理 |
|
||
| `/cleaning` | 数据清理 | DependPermission | 定向清洗操作 |
|
||
| `/analytics` | 数据分析 | 无 | 趋势、来源分布统计 |
|
||
| `/company` | 公司搜索 | 无 | 公司信息查询 |
|
||
|
||
**认证机制**:JWT(HS256,有效期 7 天),通过 `DependPermission` 依赖注入检查路由级别权限。
|
||
|
||
---
|
||
|
||
## 关键依赖与配置
|
||
|
||
配置集中在 `app/settings/config.py`(`pydantic-settings.BaseSettings`,支持环境变量覆盖):
|
||
|
||
```python
|
||
# 关键字段(需通过环境变量覆盖)
|
||
SECRET_KEY = "CHANGE_ME_DEV_ONLY" # JWT 签名密钥
|
||
TORTOISE_ORM.connections.default # MySQL 连接串(含密码)
|
||
CLICKHOUSE_HOST / USER / PASS # ClickHouse 连接
|
||
SMTP_USER / SMTP_PASS # 邮件凭据
|
||
```
|
||
|
||
**中间件链**(从外到内):
|
||
1. `CORSMiddleware` - 跨域(默认允许 `http://localhost:5173`)
|
||
2. `BackGroundTaskMiddleware` - 后台任务支持
|
||
3. `HttpAuditLogMiddleware` - HTTP 审计日志(排除登录接口)
|
||
4. `IpTrackingMiddleware` - IP 请求追踪
|
||
|
||
---
|
||
|
||
## 数据模型
|
||
|
||
### MySQL(Tortoise-ORM)
|
||
|
||
| 表 | 模型文件 | 说明 |
|
||
|----|----------|------|
|
||
| `user` | `app/models/admin.py` | 用户(含角色多对多) |
|
||
| `role` | `app/models/admin.py` | 角色(含菜单、API 多对多) |
|
||
| `api` | `app/models/admin.py` | 接口注册表 |
|
||
| `menu` | `app/models/admin.py` | 菜单树(parent_id 自引用) |
|
||
| `dept` | `app/models/admin.py` | 部门树 + 闭包表 |
|
||
| `auditlog` | `app/models/admin.py` | HTTP 操作审计 |
|
||
| `boss_token` | `app/models/token.py` | Boss 直聘登录 Token |
|
||
| `cleaning_*` | `app/models/cleaning.py` | 数据清洗任务状态 |
|
||
| `scheduled_task_run` / `stats_total` | `app/models/metrics.py` | 定时任务运行记录与统计汇总 |
|
||
|
||
### ClickHouse(原始数据存储)
|
||
|
||
| 表/视图 | 引擎 | 说明 |
|
||
|---------|------|------|
|
||
| `boss_job` | MergeTree | Boss 职位原始 JSON,`job_id` 去重 |
|
||
| `boss_company` | MergeTree | Boss 公司原始 JSON,`company_name` 去重 |
|
||
| `qcwy_job` | MergeTree | 前程无忧职位,`job_id + update_date_time` 去重 |
|
||
| `qcwy_company` | MergeTree | 前程无忧公司 |
|
||
| `zhilian_job` | MergeTree | 智联招聘职位,`number + first_publish_time` 去重 |
|
||
| `zhilian_company` | MergeTree | 智联招聘公司 |
|
||
| `pending_company` | ReplacingMergeTree | 待处理公司队列,`(source, company_id)` 去重 |
|
||
| `job_analytics` | VIEW | 三平台统一分析视图(UNION ALL) |
|
||
|
||
ClickHouse 表结构在 `app/core/clickhouse_init.py` 中通过 `CREATE TABLE IF NOT EXISTS` 管理。
|
||
|
||
---
|
||
|
||
## 核心服务
|
||
|
||
| 服务文件 | 职责 |
|
||
|----------|------|
|
||
| `app/services/cleaning.py` | `CleaningService`:多平台定向清洗(URL/ID/公司名/公司ID),自动识别平台 |
|
||
| `app/services/company_cleaner.py` | 公司数据自动清洗:collect 待处理 → process → 入库 |
|
||
| `app/services/analytics_service.py` | `AnalyticsService`:封装 ClickHouse 分析查询 |
|
||
| `app/services/job.py` | `DataRouterService`:数据路由入库(去重逻辑) |
|
||
| `app/services/ingest_service.py` | 批量数据摄入 |
|
||
| `app/services/crawler/boss.py` | Boss 爬虫 Service 封装(HTTP 层) |
|
||
| `app/services/crawler/qcwy.py` | 前程无忧爬虫 Service |
|
||
| `app/services/crawler/zhilian.py` | 智联招聘爬虫 Service |
|
||
| `app/repositories/clickhouse_repo.py` | ClickHouse Repository(`ClickHouseBaseRepo` + `JobAnalyticsRepo`) |
|
||
| `app/core/scheduler.py` | 定时任务:stats、ip_alert、ecs_pipeline、company_cleaning、daily_cleanup |
|
||
| `app/core/locks.py` | `DistributedLock`:基于文件/Redis 的分布式锁,防多 Worker 重复执行 |
|
||
| `app/core/algorithms/antispider.py` | 反爬虫算法(签名生成等) |
|
||
|
||
---
|
||
|
||
## 测试与质量
|
||
|
||
- 当前无测试文件,属于主要缺口。
|
||
- 代码质量工具:`ruff`(lint)、`black`(格式)、`isort`(导入排序)。
|
||
- 建议优先补充的测试:
|
||
- `CleaningService.clean_target_auto()` 的平台识别逻辑
|
||
- `DataRouterService.store_data()` 的去重逻辑
|
||
- `app/api/v1/analytics.py` 接口集成测试
|
||
|
||
---
|
||
|
||
## 常见问题 (FAQ)
|
||
|
||
**Q: 启动报 ClickHouse 连接失败?**
|
||
A: 检查 `CLICKHOUSE_HOST` 环境变量,或在 `config.py` 中将 `CLICKHOUSE_HOST` 置为空字符串跳过初始化。
|
||
|
||
**Q: 多 Worker 下任务重复执行?**
|
||
A: 通过文件锁(`.startup_lock` 目录)和 `DistributedLock` 保护,若 Worker 异常退出可能导致锁残留,手动删除 `.startup_lock` 目录即可。
|
||
|
||
**Q: 新增 API 接口后权限不生效?**
|
||
A: 在路由文件中注册路由后,重启应用会触发 `api_controller.refresh_api()` 自动扫描 FastAPI 路由表并更新 `api` 表,然后在角色管理中分配权限。
|
||
|
||
---
|
||
|
||
## 相关文件清单
|
||
|
||
```
|
||
app/
|
||
├── __init__.py # 应用工厂 create_app()
|
||
├── settings/config.py # 全局配置(Settings)
|
||
├── api/v1/__init__.py # 路由聚合
|
||
├── api/v1/analytics.py # 数据分析接口
|
||
├── api/v1/cleaning/ # 数据清理接口
|
||
├── api/v1/job/ # 数据入库接口
|
||
├── api/v1/keyword/ # 关键词管理接口
|
||
├── api/v1/company/ # 公司搜索接口
|
||
├── controllers/ # 业务控制器(CRUD 封装)
|
||
├── core/
|
||
│ ├── init_app.py # lifespan 初始化
|
||
│ ├── scheduler.py # APScheduler 定时任务
|
||
│ ├── clickhouse.py # ClickHouse 连接管理
|
||
│ ├── clickhouse_init.py # ClickHouse 表/视图 DDL
|
||
│ ├── locks.py # 分布式锁
|
||
│ ├── middlewares.py # 中间件
|
||
│ └── algorithms/ # 签名/反爬虫算法
|
||
├── models/
|
||
│ ├── admin.py # User, Role, Api, Menu, Dept, AuditLog
|
||
│ ├── token.py # BossToken
|
||
│ ├── metrics.py # ScheduledTaskRun, StatsTotal
|
||
│ └── cleaning.py # 清洗任务状态
|
||
├── repositories/
|
||
│ └── clickhouse_repo.py # ClickHouse 查询仓库
|
||
├── services/
|
||
│ ├── cleaning.py # CleaningService
|
||
│ ├── company_cleaner.py # 公司自动清洗
|
||
│ ├── analytics_service.py # 数据分析 Service
|
||
│ ├── job.py # DataRouterService(数据入库路由)
|
||
│ └── crawler/ # 各平台爬虫 Service 封装
|
||
└── schemas/ # Pydantic 请求/响应 Schema
|
||
```
|
||
|
||
---
|
||
|
||
## 变更记录 (Changelog)
|
||
|
||
| 日期 | 说明 |
|
||
|------|------|
|
||
| 2026-03-20 | 初始化模块文档 |
|