# Tasks.md:小红书 / 抖音热榜评论抓取 + AI 分析报告工具 ## 1. 文档信息 - 文档阶段:Tasks(开发任务拆解) - 需求依据:`docs/PRD.md`、`docs/FeatureSummary.md` - 技术依据:`docs/DevelopmentPlan.md` - UI 依据:`docs/UIDesign.md` - 测试依据:`docs/TDD.md` - API Spike 依据:`docs/API-Spike-Xiaohongshu.md`、`docs/API-Spike-Douyin.md` - 当前目标:将 MVP 拆解为 4 天内可执行、可测试、可验收的开发任务 --- ## 2. 开发总原则 1. 遵循 TDD:先写失败测试,再写最小实现,再重构。 2. MVP 优先:先跑通主链路,再做 P1 优化。 3. 不使用真实 TikHub / AI API 作为单元测试依赖。 4. 外部 API、AI 响应、字段缺失、限流等场景必须通过 mock 覆盖。 5. 任务主状态只使用 `running` / `success` / `failed`;AI 质量使用 `analysis_status` 和 `analysis_success_rate` 表示,不新增“部分失败”任务状态。 6. 页面展示和导出必须读取同一份结构化报告数据。 7. API Key、AI Key 不写入代码仓库。 --- ## 3. 目标目录结构 ```text app/ main.py config.py db.py models.py schemas.py services/ task_service.py crawl_service.py ai_service.py report_service.py export_service.py platforms/ base.py xiaohongshu.py douyin.py templates/ base.html index.html tasks/detail.html hotspots/report.html items/detail.html partials/task_rows.html macros/status_badge.html macros/sentiment_badge.html macros/label_tags.html static/ app.css app.js prompts/ comment_analysis.txt report_summary.txt tests/ conftest.py fixtures/ unit/ integration/ Dockerfile docker-compose.yml .env.example pyproject.toml ``` --- ## 4. 里程碑安排 | 日期 | 目标 | 验收结果 | |---|---|---| | Day 1 | 项目骨架、配置、数据库、任务创建、基础页面 | 可启动、可创建任务、任务列表可见 | | Day 2 | 小红书 / 抖音抓取链路、字段映射、评论分页、容错 | mock 测试中两平台链路跑通 | | Day 3 | AI 分析、报告生成、统计一致性 | 评论有情绪和标签,报告可生成 | | Day 4 | 页面完善、导出、Docker、手工验收 | Docker 启动,双平台默认任务可演示 | --- ## 5. Day 1:项目骨架、数据模型、任务框架 ### T01 初始化项目结构与依赖 **目标**:创建 FastAPI 单体项目骨架。 **涉及文件**: - 创建:`app/main.py` - 创建:`app/config.py` - 创建:`app/db.py` - 创建:`app/models.py` - 创建:`app/schemas.py` - 创建:`pyproject.toml` 或 `requirements.txt` - 创建:`.env.example` **步骤**: - [ ] 创建 `app/`、`app/services/`、`app/platforms/`、`app/templates/`、`app/static/`、`tests/` 目录。 - [ ] 添加 FastAPI、SQLAlchemy、Pydantic、httpx、Jinja2、pytest、respx、beautifulsoup4 等依赖。 - [ ] 在 `app/main.py` 中创建 FastAPI 应用。 - [ ] 实现 `/health`,返回 `{ "status": "ok" }`。 - [ ] 编写 `tests/unit/test_config.py`,覆盖默认配置和环境变量读取。 - [ ] 编写 `/health` 集成测试。 - [ ] 运行 `pytest tests/unit tests/integration -q`。 **验收**: - 本地可启动 FastAPI。 - `/health` 返回 200。 - 配置测试通过。 ### T02 配置管理与环境变量 **目标**:集中管理 TikHub、AI、数据库、HTTP 超时和任务配置。 **涉及文件**: - 修改:`app/config.py` - 修改:`.env.example` - 测试:`tests/unit/test_config.py` **配置项**: - `APP_ENV` - `DATABASE_URL` - `TIKHUB_API_KEY` - `TIKHUB_BASE_URL` - `AI_PROVIDER` - `AI_BASE_URL` - `AI_API_KEY` - `AI_MODEL` - `AI_BATCH_SIZE` - `AI_CONCURRENCY` - `AI_MAX_RETRIES` - `AI_TIMEOUT_SECONDS` - `HTTP_TIMEOUT_SECONDS` - `HTTP_MAX_RETRIES` - `CRAWL_PAGE_INTERVAL_SECONDS=1.5`:评论分页请求间隔秒数,支持浮点数,默认 1.5 秒 **步骤**: - [ ] 先写配置默认值测试。 - [ ] 实现 Pydantic Settings 或等价配置类。 - [ ] 校验 `AI_CONCURRENCY` 默认值为 2,硬上限不超过 3。 - [ ] 校验 `AI_MAX_RETRIES` 默认值为 3。 - [ ] 补充 `.env.example`。 - [ ] 写测试:`CRAWL_PAGE_INTERVAL_SECONDS` 可从环境变量读取,默认值为 1.5。 - [ ] 在 `.env.example` 中补充该配置项及注释说明。 **验收**: - 配置测试通过。 - `.env.example` 不包含真实 Key。 ### T03 数据库初始化与模型 **目标**:实现 SQLite + SQLAlchemy 数据模型。 **涉及文件**: - 修改:`app/db.py` - 修改:`app/models.py` - 测试:`tests/unit/test_models.py` **表结构**: - `tasks` - `hotspots` - `content_items` - `comments` - `reports` **步骤**: - [ ] 写 `tests/unit/test_models.py`,断言所有表可创建。 - [ ] 实现 SQLAlchemy Base、engine、session。 - [ ] SQLite 启用 `check_same_thread=False`、`timeout=10`、WAL。 - [ ] 实现 `Base.metadata.create_all(engine)` 启动初始化。 - [ ] 实现 `tasks.analysis_status`、`analysis_success_rate`、进度字段。 - [ ] 实现 reports 表业务约束在应用层校验所需字段。 - [ ] 【性能预留索引,不影响功能验收】在 comments 表上添加 `(task_id, content_item_id)` 联合索引。 - [ ] 【性能预留索引,不影响功能验收】在 content_items 表上添加 `(task_id, hotspot_id)` 联合索引。 - [ ] 【性能预留索引,不影响功能验收】在 reports 表上添加 `(task_id, report_type)` 联合索引。 **验收**: - 内存 SQLite 测试可创建并销毁全部表。 - `Task.status` 支持 `running` / `success` / `failed`。 - `analysis_status=insufficient` 不改变 `Task.status`。 ### T04 任务创建 API 与单任务执行器 **目标**:用户可创建任务,后台任务框架可排队执行。 **涉及文件**: - 修改:`app/schemas.py` - 创建:`app/services/task_service.py` - 修改:`app/main.py` - 测试:`tests/integration/test_task_creation.py` - 测试:`tests/unit/test_task_executor.py` **接口**: - `POST /api/tasks` - `GET /api/tasks` - `GET /api/tasks/{task_id}` **步骤**: - [ ] 写创建任务 API 测试,合法参数返回 `task_id` 和 `status`。 - [ ] 写非法参数测试:平台非法、热点数量越界、内容条目数越界、评论数越界。 - [ ] 实现 `CreateTaskRequest` schema。 - [ ] 实现 `ThreadPoolExecutor(max_workers=1)`。 - [ ] 在 `CreateTaskRequest` 处理逻辑中,查询当前是否存在 `status=running` 的任务;若存在,直接返回 HTTP 400,响应体为 `{"detail": "当前有正在运行的任务,请稍后再试"}`,不创建新任务。 - [ ] 写测试:当已有 `status=running` 任务时,`POST /api/tasks` 返回 400。 - [ ] 写测试:当无 running 任务时,`POST /api/tasks` 正常创建并返回 200/201。 - [ ] 创建任务时保存平台、配置规模、创建时间、状态和进度字段。 - [ ] 同一平台重复创建任务时生成独立任务。 - [ ] 实现任务列表查询。 **验收**: - 合法任务可创建。 - 非法配置返回 422。 - 任务执行器为单 worker。 ### T05 僵尸任务恢复 **目标**:应用重启后,将遗留 running 任务标记失败。 **涉及文件**: - 修改:`app/main.py` - 修改:`app/services/task_service.py` - 测试:`tests/integration/test_task_recovery.py` **步骤**: - [ ] 写测试:数据库中存在 `status=running` 的任务。 - [ ] 应用 lifespan 启动时执行恢复逻辑。 - [ ] 将 running 任务更新为 failed。 - [ ] 写入 `error_stage=system`、`error_type=unexpected_restart`、`error_message=系统重启,任务被中断`。 **验收**: - 重启恢复测试通过。 ### T06 首页 / 任务列表基础页面 **目标**:用户可在页面创建任务并查看任务列表。 **涉及文件**: - 创建:`app/templates/base.html` - 创建:`app/templates/index.html` - 创建:`app/templates/partials/task_rows.html` - 创建:`app/static/app.css` - 创建:`app/static/app.js` - 修改:`app/main.py` - 测试:`tests/integration/test_routes.py` - 测试:`tests/unit/test_template_filters.py` **步骤**: - [ ] 创建 `base.html`,包含 Bootstrap 5 CDN 和主布局。 - [ ] 创建首页任务表单:平台、热点数量、每热点内容数、每内容评论数。 - [ ] 添加规模预估提示。 - [ ] 添加任务列表:任务 ID、平台、创建时间、配置规模、进度、状态、操作。 - [ ] 实现异步 `fetch("/api/tasks")` 提交。 - [ ] 实现手动刷新按钮。 - [ ] 注册状态 Badge 渲染逻辑或 Macro。 - [ ] 测试首页无任务空状态。 - [ ] 测试状态文案不在模板中散落硬编码。 - [ ] 前端实时计算规模预估值:`hotspot_limit × item_limit_per_hotspot × comment_limit_per_item`,默认展示 1250(5×5×50)。 - [ ] 任意配置项输入值变化时立即更新预估值显示,无需点击提交。 - [ ] 写集成测试:首页默认预估规模展示为 1250。 - [ ] 在 `base.html` 中实现面包屑组件,使用 Bootstrap `