bili-fav

咻咻满 Reaction 视频数据看板与收藏夹管理工具。

项目以 B 站年度收藏夹为可信视频来源,补充关键词发现和 Telegram 人工确认,持续采集 reaction 视频的七项数据与咻咻满粉丝数,并提供本地数据看板。现有的收藏夹排序工具仍保留并作为一键加入后的排序能力基础。

当前状态:P0(数据底座与收藏夹同步)已实施,P1 待开始。

当前已可用:扫码授权、收藏夹读取、排序计划生成、执行与校验;SQLite 建库迁移、收藏夹首次导入与增量同步、失效识别、黑名单种子。

详细业务口径、接口验证和风险记录见 project.md;开发架构与实施计划见 DEVELOPMENT.md。

功能概览

功能 状态 说明
收藏夹排序 可用 同一 UP 连续,组内按发布时间倒序,组间按该 UP 最早视频发布时间倒序。
扫码授权与 Cookie 续期 可用 本地生成二维码;更新身份 Cookie 时保留设备指纹。
收藏夹同步与首次导入 可用(P0) 监控已配置年度夹,自动发现人工新收藏的视频与失效资源。
视频日快照 规划(P1) 逐条采集播放、点赞、投币、收藏、转发、评论、弹幕。
粉丝追踪 规划(P1) 每日记录咻咻满等配置 UP 的粉丝数。
本地数据看板 规划(P2) 总览、榜单、视频/UP 详情、粉丝曲线、候选池和系统状态。
Telegram 发现与一键加入 规划(P3) 每小时发现候选,支持收藏、忽略、拉黑和收藏夹内定位。

核心工作流

关键词搜索(补漏) ──► 候选池 / Telegram 人工确认 ──► 收藏夹 + 视频库
                                                      │
人工加入年度收藏夹 ──► 收藏夹同步(真相源)───────────┤
                                                      ▼
                                              每日指标与粉丝快照
                                                      ▼
                                                   本地看板
  • 收录范围:只收录他人观看、试听或点评咻咻满内容的 reaction 视频;最终是否收录由人工确认。
  • 收藏夹是真相源:手工加入已配置年度夹的视频自动入库;关键词搜索仅负责发现候选。
  • 黑名单仅作用于发现:已收藏或已入库的黑名单 UP 视频不会被清理,也会继续追踪。
  • 年度夹不自动创建或切换:同一 UP 的新视频优先进入该 UP 最早视频所在的收藏夹;容量接近上限时预警,失败时告警,不擅自改夹。
  • 数据不回填:B 站不提供任意日期的历史指标;新视频从首次入库日起开始积累快照。

本地开发环境

项目默认使用 Python 3.14 和 uv。本地开发、测试和现有排序工具的运行均不依赖 Docker、Node.js、数据库服务或宿主机 cron。

# 在项目根目录初始化或同步环境
uv sync --all-groups

# 确认锁定的解释器版本
uv run python --version

# 查看现有 CLI 帮助
uv run bili-fav help

完整的 uv 使用方式、依赖规范、架构与开发约定见 DEVELOPMENT.md。

P0:数据底座与收藏夹同步

P0 已实现 SQLite 迁移、配置热加载、B 站只读客户端、收藏夹首次导入与增量同步、infos 全量元数据刷新、失效识别、容量预警和黑名单种子。所有请求均为只读,不会修改收藏夹。

# 建库、执行迁移、写入配置文件夹与黑名单种子(离线)
uv run python app.py init

# 首次导入或增量同步配置中的年度收藏夹(只读联网)
uv run python app.py sync

# 按 folder_sync_minutes 常驻周期同步;--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 条时预警,系统绝不自动换夹。

配置

复制样例配置,并填写 B 站账号信息:

Copy-Item config.example.json config.json

config.json 已被 .gitignore 忽略,不得提交。其中:

  • mid / cookie / csrf:B 站账号 UID、完整 Cookie 与 bili_jct(兼容 favsort.py 的扁平写法;也支持 bilibili 嵌套对象);
  • overrides:可选,为代发或联合投稿视频指定归属 UP;
  • folders:年度收藏夹配置(year + media_id + title),系统不自动建夹;
  • up_blacklist_seed:首次启动写入数据库的 UP 黑名单种子;
  • track_fans:需要每日追踪粉丝数的 UP mid;
  • storage:数据库与备份目录;
  • schedule / notify / classify / heat_weights:任务节奏、通知阈值、分类规则和热度权重。

完整配置口径以 project.md 和 DEVELOPMENT.md 为准。

当前可用:收藏夹排序 CLI

所有命令建议通过 uv run 执行:

# 查看全部命令;无需 config.json
uv run bili-fav help

# 扫码登录,更新 config.json 中失效的身份 Cookie
uv run bili-fav auth
uv run bili-fav auth --check

# 列出本人创建的收藏夹
uv run bili-fav folders

# 只读:拉取收藏夹,生成排序计划
uv run bili-fav plan <media_id> -v

# 查看或离线重算已有计划
uv run bili-fav show <media_id>
uv run bili-fav replan <media_id>

# 写操作:按计划逐步排序;完成后校验
uv run bili-fav run <media_id>
uv run bili-fav verify <media_id>

plan 会生成 data/plan-<media_id>.json,其中含原始顺序、目标顺序、移动脚本及视频元数据缓存。run 直接使用该计划,不会重复请求 infos;如排序算法变更,可用 replan 离线重算。

排序规则

  1. 同一 UP 必须连续:按 upper.mid 分组,组内按发布时间倒序;发布时间相同则按 avid 升序。
  2. 组间按最早投稿倒序:取该 UP 在当前收藏夹中最早视频的发布时间作为组键,按组键倒序;并列时按组内最小 avid 升序。
  3. 失效或异常资源置底:保持它们原有的相对顺序。
  4. 可配置归属修正:config.json 的 overrides 可为指定视频指定实际归属 UP。

组间规则是有意设计:某个 UP 只要存在较老视频,即使近期继续投稿,整个分组也会靠后。

扫码授权

当接口返回 -101 或 Cookie 即将过期时,运行:

uv run bili-fav auth
uv run bili-fav auth --check

授权流程在本地生成二维码图片并等待手机客户端扫码确认。成功后:

  • 更新 SESSDATA、bili_jct、DedeUserID、sid 等身份字段;
  • 保留 buvid3、buvid4、_uuid、buvid_fp 等设备指纹;
  • 将 csrf 同步为新的 bili_jct;
  • 原子写入 config.json,并保留 config.json.bak;
  • 通过 x/web-interface/nav 验证新登录态,失败时自动回滚。

常用选项:

uv run bili-fav auth --no-browser   # 只生成二维码图片并输出路径
uv run bili-fav auth --timeout 180  # 修改扫码等待时间(秒)

B 站访问与安全约束

接口 当前用途 身份 Cookie
fav/resource/ids 收藏夹资源 ID 不需要账号身份;可匿名读取。
fav/resource/infos 收藏夹元数据 不需要账号身份,但需要设备指纹,完全无 Cookie 时可能返回 HTTP 412。
fav/folder/created/list-all 列出自建收藏夹 需要完整登录 Cookie。
fav/resource/sort 收藏夹排序 写操作;需要完整 Cookie 和 csrf。

现有工具对 ids / infos 默认剥离账号身份 Cookie,仅保留设备指纹;如果只读请求失败,才使用完整 Cookie 重试。所有写操作使用完整 Cookie 与 CSRF。

x/v3/fav/resource/sort 的实测语义为:

sort=A:2:B:2  →  将 B 插到 A 之后

运行排序时会重新读取实际顺序、逐步回读校验,并在收藏夹内容于执行期间变动时中止,避免用过期计划强制排序。写操作存在风险,请确认计划后再执行;中断后可直接再次运行 run 继续收敛。

测试

测试全部离线运行,外部接口只在 transport 边界用真实响应形状的 Mock 替换:

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 契约、分块、缺失与重试
uv run python tests/test_folder_sync.py     # 首次导入、差集、失效识别、容量预警
uv run python tests/test_scheduler.py       # 内置调度器到期/失败隔离
uv run python tests/test_logging.py         # JSON 日志脱敏
uv run python tests/test_cli.py             # CLI 离线路径

运行期文件

config.json.bak                最近一次 auth 更新前的配置备份
data/plan-<media_id>.json     排序计划、顺序快照和元数据缓存
data/journal-<media_id>.jsonl 排序执行日志
data/app.db                    P0 起的 SQLite 数据库(收藏夹、视频、黑名单)
data/backup/                  数据库迁移前的自动备份

文档索引

  • project.md:完整可行性分析、业务口径、接口验证、数据模型草案和风险清单。
  • DEVELOPMENT.md:开发架构、数据库迁移、API、调度、Telegram 与分阶段实施计划。
S
Description
No description provided
Readme
2.6 MiB
0 Stars 2 Watchers 0 Forks
Languages
Python 83.4%
JavaScript 13%
CSS 3.2%
HTML 0.2%
Shell 0.1%
Other 0.1%