# bili-fav **咻咻满 Reaction 视频数据看板与收藏夹管理工具。** 项目以 B 站年度收藏夹为可信视频来源,补充关键词发现和 Telegram 人工确认,持续采集 reaction 视频的七项数据与咻咻满粉丝数,并提供本地数据看板。现有的收藏夹排序工具仍保留并作为一键加入后的排序能力基础。 > 当前状态:**P0(数据底座与收藏夹同步)、P1(快照与粉丝追踪)已实施;P2 待开始。** > > 当前已可用:扫码授权、收藏夹读取、排序计划生成、执行与校验;SQLite 建库迁移、收藏夹首次导入与增量同步、失效识别、黑名单种子;每日七项视频快照、粉丝数快照、失败占位、断点续跑与日备份。 > > 详细业务口径、接口验证和风险记录见 [project.md](project.md);开发架构与实施计划见 [DEVELOPMENT.md](DEVELOPMENT.md)。 ## 功能概览 | 功能 | 状态 | 说明 | |---|---|---| | 收藏夹排序 | 可用 | 同一 UP 连续,组内按发布时间倒序,组间按该 UP 最早视频发布时间倒序。 | | 扫码授权与 Cookie 续期 | 可用 | 本地生成二维码;更新身份 Cookie 时保留设备指纹。 | | 收藏夹同步与首次导入 | 可用(P0) | 监控已配置年度夹,自动发现人工新收藏的视频与失效资源。 | | 视频日快照 | 可用(P1) | 逐条采集播放、点赞、投币、收藏、转发、评论、弹幕。 | | 粉丝追踪 | 可用(P1) | 每日记录咻咻满等配置 UP 的粉丝数。 | | 本地数据看板 | 规划(P2) | 总览、榜单、视频/UP 详情、粉丝曲线、候选池和系统状态。 | | Telegram 发现与一键加入 | 规划(P3) | 每小时发现候选,支持收藏、忽略、拉黑和收藏夹内定位。 | ## 核心工作流 ```text 关键词搜索(补漏) ──► 候选池 / Telegram 人工确认 ──► 收藏夹 + 视频库 │ 人工加入年度收藏夹 ──► 收藏夹同步(真相源)───────────┤ ▼ 每日指标与粉丝快照 ▼ 本地看板 ``` - **收录范围**:只收录他人观看、试听或点评咻咻满内容的 reaction 视频;最终是否收录由人工确认。 - **收藏夹是真相源**:手工加入已配置年度夹的视频自动入库;关键词搜索仅负责发现候选。 - **黑名单仅作用于发现**:已收藏或已入库的黑名单 UP 视频不会被清理,也会继续追踪。 - **年度夹不自动创建或切换**:同一 UP 的新视频优先进入该 UP 最早视频所在的收藏夹;容量接近上限时预警,失败时告警,不擅自改夹。 - **数据不回填**:B 站不提供任意日期的历史指标;新视频从首次入库日起开始积累快照。 ## 本地开发环境 项目默认使用 **Python 3.14** 和 [uv](https://docs.astral.sh/uv/)。本地开发、测试和现有排序工具的运行均不依赖 Docker、Node.js、数据库服务或宿主机 cron。 ```powershell # 在项目根目录初始化或同步环境 uv sync --all-groups # 确认锁定的解释器版本 uv run python --version # 查看现有 CLI 帮助 uv run bili-fav help ``` 完整的 `uv` 使用方式、依赖规范、架构与开发约定见 [DEVELOPMENT.md](DEVELOPMENT.md)。 ## P0:数据底座与收藏夹同步 P0 已实现 SQLite 迁移、配置热加载、B 站只读客户端、收藏夹首次导入与增量同步、`infos` 全量元数据刷新、失效识别、容量预警和黑名单种子。所有请求均为只读,不会修改收藏夹。 ```powershell # 建库、执行迁移、写入配置文件夹与黑名单种子(离线) uv run python app.py init # 首次导入或增量同步配置中的年度收藏夹(只读联网) uv run python app.py sync # 按配置周期常驻运行收藏夹同步 + 每日快照;--once 只跑一次到期任务 uv run python app.py run uv run python app.py run --once # 强制全量刷新元数据(每 6 小时自动执行一次) uv run python app.py sync --full # 查看库内状态(离线) uv run python app.py status ``` - 数据写入 `data/app.db`(SQLite WAL);升级已有数据库前会自动备份到 `data/backup/`; - 内置调度器按 `schedule.folder_sync_minutes` 周期运行,`run` 常驻、`sync` 单次; - `infos` 静默缺失或 `attr=9` 的资源标记为 `removed`,保留历史; - 从收藏夹移除的资源标记为 `unfaved`,仍保留数据; - 黑名单只作为发现阶段的种子写入,**不会过滤收藏夹同步**; - 收藏夹达到 950 条时预警,系统绝不自动换夹。 ## P1:每日快照与粉丝追踪 P1 已实现每日七项视频指标快照、咻咻满粉丝数快照、失败占位、断点续跑、Cookie 失效告警和 SQLite 日备份。 ```powershell # 采集当日快照与粉丝数(只读联网,约 18~20 分钟 / 795 条) uv run python app.py snapshot # 忽略当日完成标记,重新采集 uv run python app.py snapshot --force # 分别为只读和写入账号扫码授权(默认 read) uv run python app.py auth uv run python app.py auth --account write # 检查指定账号或两套账号的登录态 uv run python app.py auth-check --account read uv run python app.py auth-check --account all ``` - `snapshot` 对 `active` / `unfaved` 视频逐条请求 `view`,每条请求间隔 1.0~1.6 秒; - 成功写入 `snapshot` 的七项指标;同日 `ok=1` 的记录直接跳过,可断点续跑; - 视频不可访问(`-404` / `62002` / `62012`)标记为 `removed`; - 其他错误重试 3 次,仍失败写入 `ok=0` 和错误信息,不写伪造的零值; - 粉丝数写入 `up_stat`,失败同样写 `ok=0`; - 当日全部视频与粉丝采集成功后写入完成标记;服务启动时若当天未完成会自动补跑; - 每次采集后生成 `data/backup/app-YYYYMMDD.db`,按 `storage.backup_keep_days` 清理旧日备份; - Cookie 失效只告警,不阻塞匿名 `view` 采集;P0/P1 只使用 `bilibili.read`。 首次真实全量采集结果:795 条视频全部成功、0 失败、0 移除,耗时约 19 分钟;粉丝 `follower=2767270`;日备份为 `data/backup/app-20261031.db`。 ## 配置 复制样例配置,并填写 B 站账号信息: ```powershell Copy-Item config.example.json config.json ``` `config.json` 已被 `.gitignore` 忽略,**不得提交**。配置必须使用双账号格式: ```json { "bilibili": { "read": { "mid": 0, "cookie": "...", "csrf": "..." }, "write": { "mid": 0, "cookie": "...", "csrf": "..." } } } ``` - `bilibili.read`:年度收藏夹同步、视频数据快照、粉丝数与其他只读查询使用; - `bilibili.write`:后续加入目标收藏夹、回读验证与现有 `favsort.py` 排序使用; - 两个账号的 Cookie、CSRF 与设备指纹严格隔离;顶层 `mid` / `cookie` / `csrf` **不再支持**; - `overrides`:可选,为代发或联合投稿视频指定归属 UP; - `folders`:年度收藏夹配置(`year` + `media_id` + `title`),系统不自动建夹; - `up_blacklist_seed`:首次启动写入数据库的 UP 黑名单种子; - `track_fans`:需要每日追踪粉丝数的 UP mid; - `storage`:数据库与备份目录; - `schedule` / `notify` / `classify` / `heat_weights`:任务节奏、通知阈值、分类规则和热度权重。 完整配置口径以 [project.md](project.md) 和 [DEVELOPMENT.md](DEVELOPMENT.md) 为准。 ## 当前可用:收藏夹排序 CLI 所有命令建议通过 `uv run` 执行: ```powershell # 查看全部命令;无需 config.json uv run bili-fav help # 为写账号扫码登录与检查状态(认证入口统一在 app.py) uv run python app.py auth --account write uv run python app.py auth-check --account write # 列出本人创建的收藏夹 uv run bili-fav folders # 只读:拉取收藏夹,生成排序计划 uv run bili-fav plan -v # 查看或离线重算已有计划 uv run bili-fav show uv run bili-fav replan # 写操作:按计划逐步排序;完成后校验 uv run bili-fav run uv run bili-fav verify ``` `plan` 会生成 `data/plan-.json`,其中含原始顺序、目标顺序、移动脚本及视频元数据缓存。`run` 直接使用该计划,不会重复请求 `infos`;如排序算法变更,可用 `replan` 离线重算。 ### 排序规则 1. **同一 UP 必须连续**:按 `upper.mid` 分组,组内按发布时间倒序;发布时间相同则按 `avid` 升序。 2. **组间按最早投稿倒序**:取该 UP 在当前收藏夹中最早视频的发布时间作为组键,按组键倒序;并列时按组内最小 `avid` 升序。 3. **失效或异常资源置底**:保持它们原有的相对顺序。 4. **可配置归属修正**:`config.json` 的 `overrides` 可为指定视频指定实际归属 UP。 > 组间规则是有意设计:某个 UP 只要存在较老视频,即使近期继续投稿,整个分组也会靠后。 ## 扫码授权 当接口返回 `-101` 或 Cookie 即将过期时,使用统一认证入口: ```powershell uv run python app.py auth --account read uv run python app.py auth --account write uv run python app.py auth-check --account all ``` 授权流程在本地生成二维码图片并等待手机客户端扫码确认。成功后: - 更新 `SESSDATA`、`bili_jct`、`DedeUserID`、`sid` 等身份字段; - 保留 `buvid3`、`buvid4`、`_uuid`、`buvid_fp` 等设备指纹; - 将选中账号的 `csrf` 同步为新的 `bili_jct`,并从 `nav` 回写该账号实际 mid; - 原子写入 `config.json`,并保留 `config.json.bak`; - 通过 `x/web-interface/nav` 验证新登录态,失败时自动回滚;不会修改另一个账号。 常用选项: ```powershell uv run python app.py auth --account write --no-browser uv run python app.py auth --account read --timeout 180 ``` ## B 站访问与安全约束 | 接口 | 当前用途 | 身份 Cookie | |---|---|---| | `fav/resource/ids` / `infos` | 年度收藏夹同步与排序计划 | `read` 用于 P0;`favsort.py` 计划使用 `write`。 | | `view` / `relation/stat` / `nav` | P1 快照与 read 登录态 | `read`。 | | `fav/folder/created/list-all` | 列出目标自建收藏夹 | `write`。 | | `fav/resource/deal` / `sort` | 加入收藏夹、收藏夹排序 | `write`,需要完整 Cookie 和 CSRF。 | 只读客户端对 `ids` / `infos` 默认剥离 `read` 身份 Cookie,仅保留该账号设备指纹;如果失败才使用完整 `read` Cookie 重试。写操作一律使用完整 `write` Cookie 与 CSRF。 `x/v3/fav/resource/sort` 的实测语义为: ```text sort=A:2:B:2 → 将 B 插到 A 之后 ``` 运行排序时会重新读取实际顺序、逐步回读校验,并在收藏夹内容于执行期间变动时中止,避免用过期计划强制排序。写操作存在风险,请确认计划后再执行;中断后可直接再次运行 `run` 继续收敛。 ## 测试 测试全部离线运行,外部接口只在 transport 边界用真实响应形状的 Mock 替换: ```powershell uv run python tests/test_auth.py # Cookie 合并、设备指纹、Set-Cookie 解析 uv run python tests/test_moves.py # 排序移动脚本:随机排列与头部用例 uv run python tests/test_config.py # 配置加载、校验、ENV 覆盖与热加载 uv run python tests/test_migrations.py # 迁移、备份、回滚与保留期 uv run python tests/test_database.py # 单写队列、事务与并发 uv run python tests/test_repository.py # 收藏夹/视频状态机与黑名单 uv run python tests/test_bilibili_client.py # ids/infos/view/fans/nav 契约与重试 uv run python tests/test_folder_sync.py # 首次导入、差集、失效识别、容量预警 uv run python tests/test_snapshot.py # 七项快照、断点续跑、失败占位、粉丝 uv run python tests/test_maintenance.py # 日备份与保留期 uv run python tests/test_timeutil.py # 上海时区与每日任务时间 uv run python tests/test_scheduler.py # 内置调度器到期/失败隔离 uv run python tests/test_logging.py # JSON 日志脱敏 uv run python tests/test_cli.py # CLI 离线路径 ``` ## 运行期文件 ```text config.json.bak 最近一次 auth 更新前的配置备份 data/plan-.json 排序计划、顺序快照和元数据缓存 data/journal-.jsonl 排序执行日志 data/app.db SQLite 数据库(收藏夹、视频、快照、粉丝、黑名单) data/backup/app-YYYYMMDD.db 每日快照后的 SQLite 备份 data/backup/app-pre-v*.db 数据库迁移前的自动备份 ``` ## 文档索引 - [project.md](project.md):完整可行性分析、业务口径、接口验证、数据模型草案和风险清单。 - [DEVELOPMENT.md](DEVELOPMENT.md):开发架构、数据库迁移、API、调度、Telegram 与分阶段实施计划。