docs: document duration efficiency, up follower snapshot and nav split

This commit is contained in:
kairee committed 2026-11-01 11:36:34 +08:00
1 parent c0b0286395
commit cb9e8e031b
2 files changed
+101 -22

No files matched your search

+50 -10
View File
@@ -100,6 +100,10 @@ uv run python app.py run --once
uv run python app.py snapshot uv run python app.py snapshot
uv run python app.py snapshot --force uv run python app.py snapshot --force
# 回填历史视频的 UP 粉丝数快照(第 9 轮;只补空值)
uv run python app.py backfill-followers
uv run python app.py backfill-followers --dry-run
# 检查 Cookie 登录态(P1) # 检查 Cookie 登录态(P1)
uv run python app.py auth-check uv run python app.py auth-check
@@ -206,7 +210,7 @@ PRAGMA synchronous = NORMAL;
│ │
├── reaction_board/ ├── reaction_board/
│ ├── config.py # 配置、ENV 覆盖、mtime 热加载 │ ├── config.py # 配置、ENV 覆盖、mtime 热加载
│ ├── analytics.py # 热度、增长、互动率与封面工具 │ ├── analytics.py # 热度、增长、互动率、时长效率、EB 收缩与封面工具
│ ├── database.py # SQLite 连接、迁移、单写队列 │ ├── database.py # SQLite 连接、迁移、单写队列
│ ├── migrations.py # schema_version 与迁移 │ ├── migrations.py # schema_version 与迁移
│ ├── scheduler.py # 内置任务调度 │ ├── scheduler.py # 内置任务调度
@@ -228,6 +232,7 @@ PRAGMA synchronous = NORMAL;
│ │ ├── telegram_poller.py # getUpdates 与回调分发 │ │ ├── telegram_poller.py # getUpdates 与回调分发
│ │ ├── folder_sync.py │ │ ├── folder_sync.py
│ │ ├── snapshot.py │ │ ├── snapshot.py
│ │ ├── up_profile.py # UP 粉丝快照采集与历史回填
│ │ └── maintenance.py │ │ └── maintenance.py
│ ├── notify/telegram.py # Telegram 消息与按钮 │ ├── notify/telegram.py # Telegram 消息与按钮
│ └── web/ # P2 只读看板 │ └── web/ # P2 只读看板
@@ -521,24 +526,27 @@ P3 实现说明:
| 方法 | 路径 | 用途 | | 方法 | 路径 | 用途 |
|---|---|---| |---|---|---|
| `GET` | `/api/overview` | 首页动态、总览指标、容量、采集状态 | | `GET` | `/api/overview` | 首页动态、总览指标、容量、采集状态 |
| `GET` | `/api/videos` | 视频分页、筛选和排序(支持 added/published/heat/七项/互动/增长) | | `GET` | `/api/videos` | 视频分页、筛选和排序(支持 added/published/heat/七项/互动/增长/内容效率) |
| `GET` | `/api/videos/{aid}` | 视频详情 | | `GET` | `/api/videos/{aid}` | 视频详情(含分 P 数、入库时粉丝数、内容/互动效率) |
| `GET` | `/api/videos/{aid}/trend` | 七项趋势数据 | | `GET` | `/api/videos/{aid}/trend` | 七项趋势数据 |
| `GET` | `/api/rankings` | 视频榜或 `scope=up` 的 UP 聚合榜 | | `GET` | `/api/rankings` | 兼容旧链接;`scope=up` 时为 UP 聚合榜 |
| `GET` | `/api/ups` | UP 聚合榜单 | | `GET` | `/api/ups` | UP 聚合榜单(含总时长、播放·小时、内容效率) |
| `GET` | `/api/ups/{mid}` | UP 详情、聚合趋势和视频列表 | | `GET` | `/api/ups/{mid}` | UP 详情、聚合趋势和视频列表 |
| `GET` | `/api/fans` | 粉丝曲线与增量 | | `GET` | `/api/fans` | 粉丝曲线与增量 |
| `GET` | `/api/candidates` | 候选池(只读) | | `GET` | `/api/candidates` | 候选池(只读) |
| `GET` | `/api/system` | 最近任务、下次任务、备份、黑名单 | | `GET` | `/api/system` | 最近任务、下次任务、备份、黑名单 |
| `GET` | `/api/about` | 数据说明页当前口径(配置阈值、权重、覆盖度;无凭据) |
### 9.2 页面 ### 9.2 页面
| 页面 | 内容 | | 页面 | 内容 |
|---|---| |---|---|
| 首页 | 最新动态优先:今日增量、最新入库、最近发布、增长动态、热度速览、容量与采集状态。 | | 首页 | 最新动态优先:今日增量、最新入库、最近发布、增长动态、热度速览、容量与采集状态。 |
| 榜单 | 综合热度、七项单项、播放增量、播放增速、互动率、UP 聚合和筛选。 | | 视频(`/videos`) | 内容效率(默认)、综合热度、播放/投币/收藏/评论、互动率、播放增量、播放增速;筛选与搜索。 |
| 视频详情 | 元数据、七项指标、单指标趋势、快照表、失败标记、同 UP 对比。 | | UP主(`/ups`) | 独立入口,不再与视频混排;视频数、总时长、播放·小时、互动·小时等可分别排序。 |
| UP 页 | UP 的全部视频、聚合趋势、单视频对比和平均互动率。 | | 数据说明(`/about`) | 数据来源与更新、发布时间/入库时间/快照日期、指标公式、时长与成熟窗口筛选、粉丝快照覆盖与已知局限;数值由 `/api/about` 动态读取。 |
| 视频详情 | 元数据、分 P 数、七项指标、内容/互动效率、入库时粉丝数、单指标趋势、快照表、同 UP 对比。 |
| UP 页 | 该 UP 的全部视频、聚合趋势、单视频对比、总时长与播放·小时、入库时与当前粉丝数。 |
| 粉丝页 | 粉丝总数、日增、7 日净增、累计增长(标注起始日期);支持预设和自选日期,范围超过一年时按每月峰值日期聚合;最近记录默认 14 天并显示“较上一成功日”增量;不叠加视频数据。 | | 粉丝页 | 粉丝总数、日增、7 日净增、累计增长(标注起始日期);支持预设和自选日期,范围超过一年时按每月峰值日期聚合;最近记录默认 14 天并显示“较上一成功日”增量;不叠加视频数据。 |
| 候选池 | 待确认候选、规则命中、剩余保留时间;操作指向 Telegram/CLI。 | | 候选池 | 待确认候选、规则命中、剩余保留时间;操作指向 Telegram/CLI。 |
| 系统状态 | 最近扫描、同步、快照、下次运行、备份、鉴权和黑名单。 | | 系统状态 | 最近扫描、同步、快照、下次运行、备份、鉴权和黑名单。 |
@@ -550,7 +558,8 @@ P3 实现说明:
- `python app.py serve --preview` 校验标记,缺失时拒绝启动; - `python app.py serve --preview` 校验标记,缺失时拒绝启动;
- 预览配置不包含真实凭据,默认端口 8081,Telegram 关闭; - 预览配置不包含真实凭据,默认端口 8081,Telegram 关闭;
- 预览页面显示固定“预览数据 · 不影响真实数据库”横幅,右上角入口显示“预览”; - 预览页面显示固定“预览数据 · 不影响真实数据库”横幅,右上角入口显示“预览”;
- 重新生成预览库前必须停止预览服务,避免 Windows 文件占用。 - 重新生成预览库前必须停止预览服务,避免 Windows 文件占用;
- 第 9 轮起本地不再保留 `data/app.db` 真实副本;重新生成预览时用 `--source` 指向 `data/backup/` 中的真实库备份(如 `app-local-before-reseed-20261101.db`)。
--- ---
@@ -589,6 +598,22 @@ interaction_rate = (like + coin + favorite) / max(view, 1)
- 互动率榜要求播放至少 100; - 互动率榜要求播放至少 100;
- 样本不足两天的视频明确标注,不伪造增长数据。 - 样本不足两天的视频明确标注,不伪造增长数据。
### 10.3 时长效率与 UP 内容效率(第 9 轮)
```text
内容小时 = duration / 3600
内容效率 = view / 内容小时
互动效率 = (like + coin + favorite) / 内容小时
UP 内容效率 = (Σview + κ·μ₀) / (Σ内容分钟 + κ) * 60
```
- 分母只用总时长,不用分 P 数(B 站播放记在 bvid 上,`view/pages` 无统计含义);
- 效率榜要求 `duration >= analytics.min_duration_seconds`(默认 600 秒)且发布满 `analytics.maturity_days`(默认 14 天);
- 不引入 `log(age)` 等无界年龄项,避免系统性惩罚老视频;
- `duration` 缺失或非正数不参与效率排序;
- UP 收缩强度 `κ` 取全库 UP 总内容分钟中位数,`analytics.shrink_minutes` 可覆盖;
- 视频数与总时长并列展示、分别排序,不合成单一产出分。
--- ---
## 11. 测试与质量要求 ## 11. 测试与质量要求
@@ -615,7 +640,9 @@ uv run python tests/test_moves.py
- 看板查询的筛选、分页、增长冷启动与状态过滤; - 看板查询的筛选、分页、增长冷启动与状态过滤;
- 只读路由、鉴权、静态资源路径穿越和预览标记校验; - 只读路由、鉴权、静态资源路径穿越和预览标记校验;
- 预览库生成的确定性、单调性、异常样本与真实库隔离; - 预览库生成的确定性、单调性、异常样本与真实库隔离;
- 粉丝历史 CSV 解析、同日去重、缺口计数与幂等/替换回填。 - 粉丝历史 CSV 解析、同日去重、缺口计数与幂等/替换回填;
- UP 粉丝快照:首次写入不可覆盖、同轮去重、失败不中断、`live_since` 实时/回填标记、`backfill` 的 dry-run 与 limit;
- 时长效率:`duration` 缺失/非正数、短于门槛、未满成熟窗口的排除,EB 收缩边界(除零、负先验)。
只有当标准库测试维护成本明显过高时,才考虑通过 `uv add --dev pytest` 引入 pytest。 只有当标准库测试维护成本明显过高时,才考虑通过 `uv add --dev pytest` 引入 pytest。
@@ -702,6 +729,19 @@ uv run python tests/test_moves.py
- `serve --preview` 校验 `preview:seeded=1` 标记,预览页面显示“预览数据”横幅; - `serve --preview` 校验 `preview:seeded=1` 标记,预览页面显示“预览数据”横幅;
- 自动化测试见 `tests/test_analytics.py`、`test_preview_seed.py`、`test_web_queries.py`、`test_web_server.py`。 - 自动化测试见 `tests/test_analytics.py`、`test_preview_seed.py`、`test_web_queries.py`、`test_web_server.py`。
### 第 9 轮:时长效率榜、粉丝快照与导航拆分 ✅(2026-11-01)
- 迁移 v4:`video.pages`、`video.up_follower` / `up_follower_at` / `up_follower_backfilled`、`up_profile`;
- 收藏夹同步结束时采集缺失 UP 的粉丝数(`relation/stat`,匿名可用);`first_seen >= 运行开始 - 1h` 记为实时,更早的记为回填;
- `app.py backfill-followers`:一次性回填历史视频粉丝数,支持 `--limit` / `--dry-run`;
- 新增内容效率/互动效率榜与 UP 内容效率(Gamma–Poisson EB 收缩),过滤 < 600 秒与未满 14 天的视频;
- `analytics` 配置段:`min_duration_seconds`、`maturity_days`、`min_view_for_efficiency`、`shrink_minutes`;
- 主导航拆分:`/videos`(视频)与 `/ups`(UP主)独立;旧 `/rank` 保留兼容;
- 新增 `/about` 数据说明页与 `/api/about`;
- 卡片精简:列表只保留主指标与互动率,明细移到详情页;
- 本地只保留可再生的预览库 `data/preview/app.db`;
- 自动化测试新增 `tests/test_up_profile.py`,并扩展 `test_analytics.py`、`test_repository.py`、`test_config.py`、`test_folder_sync.py`、`test_web_queries.py`、`test_web_server.py`、`test_migrations.py`、`test_database.py`、`test_cli.py`。
### P4:可选部署 ### P4:可选部署
- 反向代理、TLS、远程访问鉴权; - 反向代理、TLS、远程访问鉴权;
+51 -12
View File
@@ -1,7 +1,7 @@
# 咻咻满 Reaction 视频数据看板 —— 可行性分析与技术路线 # 咻咻满 Reaction 视频数据看板 —— 可行性分析与技术路线
> 状态:**设计定稿;P0(数据底座与收藏夹同步)、P1(每日快照与粉丝追踪)、P2(只读本地看板)、P3(Telegram 与一键加入)已实施** > 状态:**设计定稿;P0(数据底座与收藏夹同步)、P1(每日快照与粉丝追踪)、P2(只读本地看板)、P3(Telegram 与一键加入)已实施;第 9 轮加入时长效率榜、UP 粉丝快照与导航拆分**
> 最后更新:2026-10-31(第 8 轮:P2 只读看板与预览数据落地) > 最后更新:2026-11-01(第 9 轮:时长效率榜、粉丝快照采集、视频/UP 导航拆分与数据说明页)
> B 站探测均为只读(GET),尚未调用 `fav/resource/deal`、`fav/resource/sort` > B 站探测均为只读(GET),尚未调用 `fav/resource/deal`、`fav/resource/sort`
--- ---
@@ -517,6 +517,15 @@ CREATE TABLE fav_action (
CREATE TABLE kv (k TEXT PRIMARY KEY, v TEXT); CREATE TABLE kv (k TEXT PRIMARY KEY, v TEXT);
``` ```
**第 9 轮新增(schema v4,已迁移)**
- `video.pages`:分 P 数(来自 `infos` 的 `page`),只用于详情展示与包装诊断,不参与排序;
- `video.up_follower` / `up_follower_at` / `up_follower_backfilled`:视频**入库时**的 UP 粉丝数快照;
- `up_profile(mid, name, follower_first, following_first, first_captured_at, follower_latest, last_refreshed)`:每个 UP 的首次/最近粉丝数。`follower_first` 不可被覆盖;
- 采集:收藏夹同步结束时对仍缺粉丝数的 UP 调一次 `relation/stat`(匿名可用);`first_seen >= 本次运行开始前 1 小时` 的视频记为实时采集,更早的记为回填;
- 回填:`python app.py backfill-followers [--limit N] [--dry-run]`,只补 `up_follower IS NULL` 的追踪视频;
- 基于粉丝数的榜单暂不实现,本轮只保证数据从现在起不再缺失。
**要点** **要点**
- `status` 是核心状态机: - `status` 是核心状态机:
@@ -661,6 +670,25 @@ fan_delta_cum = follower(d) - follower(首日)
- 缺失日不插值,曲线断开并标注; - 缺失日不插值,曲线断开并标注;
- 首日没有前值,第一条增量从第 2 天开始。 - 首日没有前值,第一条增量从第 2 天开始。
### 8.5 时长效率与 UP 内容效率(第 9 轮)
Reaction 视频时长差异极大(100~336 分钟),而播放是累计计数;若不加时长分母,长视频会天然占优,短视频/切片则天然吃亏。因此新增与时长相关的口径:
```
内容小时 = duration / 3600 # 多 P 的 duration 已是各 P 之和
内容效率 = view / 内容小时
互动效率 = (like + coin + favorite) / 内容小时
UP 内容效率 = EB 收缩后的 Σview / Σ内容小时
```
- 分母只用总时长,**不用分 P 数**:B 站播放记在 bvid 上,`view / pages` 没有统计含义;`pages` 仅用于详情展示与包装诊断;
- 效率榜只统计 `duration >= analytics.min_duration_seconds`(默认 600 秒)且发布满 `analytics.maturity_days`(默认 14 天)的视频;不足者标注"样本不足";
- **不用无界年龄项**:reaction 视频约两周进入平台期,`log(age)` 会系统性惩罚老视频,故采用"成熟窗口筛选"而非年龄回归;
- `duration` 为空或 ≤ 0(通常只在失效视频出现)不进入效率榜,不插补;
- UP 效率用 Gamma–Poisson 经验贝叶斯:`rate = (Σview + κ·μ₀) / (Σ内容分钟 + κ)`,`μ₀` 为全库播放/分钟,`κ` 自适应取全库 UP 总内容分钟中位数(配置 `analytics.shrink_minutes` 可覆盖,缺省回退 120 分钟);
- 视频榜默认 Tab 为内容效率,原始播放榜保留;互动单项只保留播放/投币/收藏/评论,点赞、弹幕、转发并入"互动";
- **UP 榜的"视频数"与"总时长"并列展示、分别可排序,不合成单一产出分**(两者高度共线,加权求和的权重是任意的)。
--- ---
## 9. 看板 ## 9. 看板
@@ -670,9 +698,11 @@ fan_delta_cum = follower(d) - follower(首日)
| 页面 | 内容 | | 页面 | 内容 |
|---|---| |---|---|
| 首页 | 最新动态优先:今日增量、最新入库、最近发布、增长动态、热度速览、收藏夹容量、采集状态 | | 首页 | 最新动态优先:今日增量、最新入库、最近发布、增长动态、热度速览、收藏夹容量、采集状态 |
| 榜单 | Tab:综合热度/播放/点赞/投币/收藏/转发/评论/弹幕/互动率/播放增量/播放增速;视频与 UP 范围切换;筛选与搜索 | | **视频** | Tab:内容效率/综合热度/播放/投币/收藏/评论/互动率/播放增量/播放增速;筛选与搜索 |
| 视频详情 | 元数据 + 七项指标 + 单指标趋势(7/30/90/全部)+ 同 UP 对比 + 快照表(含失败标记) | | **UP主** | 独立入口;列:视频数、总时长、总播放、播放·小时、互动·小时等,可分别排序 |
| UP 页 | 该 UP 全部视频、聚合趋势、单视频对比、平均互动率 | | 数据说明 | 数据来源与更新节奏、三个时间概念、指标公式、时长/成熟窗口筛选、粉丝快照覆盖与已知局限;数值由 `/api/about` 动态读取当前配置 |
| 视频详情 | 元数据 + 分 P 数 + 七项指标 + 内容/互动效率 + 入库时粉丝数 + 单指标趋势 + 同 UP 对比 + 快照表 |
| UP 页 | 该 UP 全部视频、聚合趋势、单视频对比、总时长/播放·小时、入库时与当前粉丝数 |
| **粉丝页** | 咻咻满粉丝数曲线 + 每日/7 日净增 + 累计增长(标注起始日期)+ 最近 14 天记录;支持 7/30/90/全部与自选起止日期,范围不超过一年按日绘制,超过一年按每月峰值日期绘制;只画粉丝,不叠加视频数据 | | **粉丝页** | 咻咻满粉丝数曲线 + 每日/7 日净增 + 累计增长(标注起始日期)+ 最近 14 天记录;支持 7/30/90/全部与自选起止日期,范围不超过一年按日绘制,超过一年按每月峰值日期绘制;只画粉丝,不叠加视频数据 |
| **候选池** | 候选、得分、通知时间、剩余 TTL;只读展示,操作指向 Telegram/CLI | | **候选池** | 候选、得分、通知时间、剩余 TTL;只读展示,操作指向 Telegram/CLI |
| **系统状态** | 最近任务、采集成功率、收藏夹同步时间、下次任务、备份、鉴权、黑名单 | | **系统状态** | 最近任务、采集成功率、收藏夹同步时间、下次任务、备份、鉴权、黑名单 |
@@ -819,12 +849,21 @@ storage:SQLite WAL,单写线程
## 14. 下一步 ## 14. 下一步
P0、P1、P2、P3 已实施。P2 交付了只读本地看板与可重复生成的 7 天预览数据: P0、P1、P2、P3 与第 9 轮已实施;P2 交付了只读本地看板与可重复生成的 7 天预览数据。
1. 首页、榜单、视频/UP 详情、粉丝曲线、候选池和系统状态页面; 第 9 轮(2026-11-01)交付:
2. 原生 ES Module + 本地 ECharts,本机默认绑定 `127.0.0.1:8080`;
3. 查询、热度、增长和互动率全部在服务端计算,前端只渲染;
4. Web 不提供业务写操作,数据管理继续通过 Telegram/CLI/数据库;
5. P3 的真实 `deal` / `sort` 待用户点击 Telegram 按钮或授权测试视频后补充验证记录。
> P4(容器化 + 反代)继续保持可选。 1. schema v4:`video.pages`、`video.up_follower*`、`up_profile`;
2. 入库时采集 UP 粉丝快照 + `python app.py backfill-followers` 历史回填(基于粉丝数的榜单暂不做);
3. 时长效率榜(内容效率/互动效率)与 UP 内容效率(EB 收缩),过滤 < 600 秒与未满 14 天的视频;
4. 主导航拆分:「榜单」→「视频」+「UP主」,两者独立页面;新增「数据说明」页(`/about` + `/api/about`);
5. 列表精简:卡片只保留主指标 + 互动率,七项明细与分 P、粉丝快照移到详情页。
仍待处理:
1. 真实 `deal` / `sort` 与 Telegram 按钮回调的补充验证记录;
2. 基于粉丝数的"破圈"维度(播放/入库时粉丝数、粉丝分段、UP 中位数)——数据已就绪,榜单未实现;
3. P4(容器化 + 反代)继续保持可选。
> 本地数据:第 9 轮起本地只保留可再生的预览库 `data/preview/app.db`(`tools/seed_preview_db.py` 生成),
> 原 `data/app.db` 真实副本已删除;需要重新生成或恢复时,用 `--source data/backup/app-local-before-reseed-20261101.db`。