Skip to content

v1.1.0

Choose a tag to compare

@Mrslippe Mrslippe released this 06 Oct 07:00
· 176 commits to main since this release

DDtoolkit v1.1.0

个人向 VTuber 帖子 / 账号证据归档工具 —— 定时抓取 B 站、微博、小红书与抖音的帖子与账号统计并归档到本地 SQLite,桌面端浏览与管理。

从 v1.0.2 到 v1.1.0 共 248 篇 devlog(119–373),主线是八件事:
① 两个新平台(小红书全链路;抖音端到端,合规总开关默认关、风险自担);
② 播放内核换成 MSE(B 站 DASH 双轨 + 清晰度 + 分P,拖动不再冻帧,地址过期自动重取);
③ 浏览器扩展(一键把四个平台的登录态同步进应用,含 HttpOnly 键与抖音 UA);
④ 使用须知闸门(首启 / 声明正文更新时读完点同意才进得去;应用版本升级不再打扰);
⑤ 通知中心(推送通道替代前端轮询 + 已读语义 + 调测页);
⑥ 界面重做一批(工具条、状态胶囊、数据视图牌堆……;档案视图本版暂时隐藏);
⑦ 轻资产(头像与封面固化到本地、缓存上限与淘汰、归档自动清理、历次头像账本);
⑧ 工程与安全(CI 落地、本机会话 token、HTML 净化、外链白名单、依赖只认锁文件)。
数据库迁移 f004 → f009(置顶动态 / 档案卡布局 / 事件图标 / 头像账本 / 轻资产索引),
首次启动会自动迁移,比以前多等一会儿。

🧾 使用须知闸门(本版所有用户都会被问一次)

启动时盖一层不可关闭的《DDToolkit 使用须知与免责声明》:读完滚到底、点「我已知悉并同意」
才进得去(不点只能退出应用;Esc、点窗外、✕ 都不生效)。

  • 正文按开源软件的写法:MIT 开源、按「现状」提供;作者仅出于学习与研究目的分享,
    不支持也未授权商业用途或违法用途;只用你自己合法持有的凭据;与第三方平台无任何关联;
    抓取内容仅供个人留存,权利人可要求移除;使用风险与后果由你自行承担(十三节全文);
  • 确认口径是"声明版本",不是"应用版本":应用从 1.1.0 升到 1.2.0 不会再问;只有须知正文改了
    (app/services/legal_notice.py 的 NOTICE_VERSION)才会再要求所有人确认一次;
  • 平时随时能在「设置 → 关于 → 用户协议」看全文、以及"你同意到哪一版、什么时候同意的";
    「查看全文」是只读的 —— 能关、绝不写库(同意只发生在启动那道闸门);
  • 本版是第一次引入须知,所以所有人都会遇到这一次;之后只有新装的用户才会看到。

🆕 新平台:小红书 与 抖音

小红书:收录走 uid 主页复核、笔记详情(标题 / 正文 / 图片 / 视频 / 可打开的原始链接)、
签名器与字段映射、外链守卫(只有白名单域能跳系统浏览器)、cookie 录入与失效判定。

抖音:适配器 + 媒体链路端到端(收录 → 首屏落库 → 图片固化 → 详情页能看 → 视频能播),
签名在本地做(浏览器只负责"铸身份"),播放走应用内代理并带 Referer。

  • ⚠️ 抖音合规总开关默认关:要在「设置 → 抓取设置 → 平台抓取」里打开才会发请求;
    关着时界面如实说"未启用"而不是"需要登录"(这一条曾被误判成"抓不到数据",devlog/338);
  • 已知限制(诚实清单):小红书不做在线探活(回执标「未在线验证」);
    抖音视频不固化到本地(每次回源取流);抖音签名需要 UA(浏览器扩展会一起同步)。

▶️ 播放:MSE 成为默认内核

  • 边下边解、按需取段(默认内核;「设置 → 外观 → 视频播放」可退回渐进式;
    取不到段表或宿主不支持时自动退,不会把播放器卡死);
  • B 站 DASH 音视频双轨 + 清晰度菜单(含会员清晰度徽标)+ 分P 菜单(以前只播第一 P);
  • 拖动 seek 不再冻帧 —— 修掉一串只在真机复现的问题:段表把四舍五入的段长累加、
    endOfStream 之后 seek 失效、防打转计数器把音轨冻死、段表时刻比媒体 tfdt 偏晚几十毫秒、
    同一段连取两次把一条轨永久冻死、缓冲末尾落在表内偏差容差里……(七次复现一次收敛,形状一致);
  • 按实测吞吐自动降一档(ABR),日志里给"实测 / 需要"两个数,链路喂得饱时一次都不报;
  • 地址过期自动重取一次并换上新地址;重取撞上自己的令牌桶就排队等(最多 12 秒),
    不假装失败也不空转刷请求;
  • 手感:按住 → 250ms = 3× 快进(松手回原速)、短按仍是快进 5 秒;全屏控件、
    hover 浮层、缓冲转圈、封面暂停键、播放意图与图标横跳都重排过;
  • 日志量收敛:httpx 的逐请求 INFO 关掉、播放诊断只留两行。

🧩 浏览器扩展(Edge / Chrome,MV3)

一键把四个平台已登录的 cookie 发给本机应用 —— 含 document.cookie 读不到的 HttpOnly 键
(SESSDATA / web_session),抖音的 UA 一起带过来,不用再"打开 DevTools 抄整条 cookie"。

  • 只发 127.0.0.1;用配对 token 认领(应用「设置 → 登录 → 浏览器扩展」里复制,
    持久化 —— 关掉应用再开不用重贴);端口在 8765–8769 自动探测;
    cookie 只在内存里过一手就发走,chrome.storage.local 里只有端口与 token;
  • 与"应用里已有那份"合并:同名以浏览器为准、已有键只增不删(浏览器铸不出的指纹键
    由应用补上,回执会写清是哪个键补的);
  • 扩展图标与桌面图标同源(同一份 LOGO 生成,32/128 两档逐字节相同);
  • 装法(一次性,详见 extension/README.md):edge://extensions → 开发人员模式 →
    「加载解压缩的扩展」→ 选本仓库 extension/ 目录 → 在应用里复制配对 token 粘进扩展设置;
  • 诚实清单:popup 只能手工验(自动化的那半是 node --test extension/test/ 与
    scripts/extension_smoke.py,popup 本身无头驱动不了);抖音只带 UA、不带 sec-ch-ua;
    cookie 过期仍要你点一下(不做后台自动同步);扩展 id 由载入路径推出、换机器会变。

🔔 通知中心:推送通道 + 已读

  • 消息(开播边沿 / 任务进度 / 完成报告 / 第三方同步 / 风控冷却)改由后端推送通道送到界面
    (text/event-stream,前端用 fetch + ReadableStream 读 —— token 不进 URL),轮询逐步退场;
  • 规则层分三组 + 倒计时;投递进度由推送"推着走";客户端事实也进面板(渠道收敛到一处);
  • 已读语义收口:瞬时消息与服务端环形缓冲里的条目在"确实送达"之后真的删掉,
    而不是只记一个已读位(drop_ring),同一个账号下次开播照样出现;
  • 面板交互重排(滑出同拍、逐条退场、分组标题常驻);另有 ui_probe --notice-lab 与调测页。

🖼️ 轻资产:头像与封面固化到本地

  • 头像:抓取时落盘 + local_assets 索引(稳定键 = 去掉签名参数的 URL)——
    微博头像签名只有约 3 小时有效,固化后不再每轮回源;抓不到时用已存的那份兜底;
  • 封面:每轮固化一部分(默认 20 张上限,高级设置可调),只固化未归档帖,
    归档后由自动清理回收;
  • 历次头像账本(哪次抓取换成了哪张图、本地文件还在不在)+ 多版本选择器;
  • 设置里那一屏:按类型的读数 / 先预览再确认真删 / 长留标记(pin 过的一律不淘汰);
  • 图片缓存仍有容量上限与"最久没用"淘汰。

🗂️ 界面

  • 档案视图本版暂时隐藏(还没开发完,按你的要求先收起来):按钮不渲染,
    深链接 ?view=profile 与深休眠恢复也一起收敛;代码与数据(卡片布局表)保留,
    把那个常量翻回 true 就能放出来;
  • 页面工具条变成按需浮片:向下滚让它让位、向上滚回来,换 V 时自动闪一次(告诉你它在那儿);
  • 状态胶囊形变动效、顶栏光条(毛玻璃 / 选中块粉底 / 亮点指示器)、日期面板年份双箭头、
    数据视图牌堆与圆点自动隐藏;
  • list / archive / card 视图左上角大标题的字色跟着底图明暗走;批量任务浮窗不再横向溢出;
  • 键盘可达性:焦点环令牌化,摘掉"全局 outline-none"那类看不见焦点的写法。

🐛 真机实测抓出来的四个问题(都留了机器判据)

  1. 抖音「所有播放源都失败」 = 签名地址过期(l= 参数就是签名时刻)→ 现在自动重取一次;
    重取撞上自己的限速就排队等(devlog/363 / 366);
  2. 扩展"DevTools 里看得见、就是读不到" → 真凶是 host permission 的 scheme:
    https:// 权限读不到非 Secure 的 cookie,而 a1 / s_v_web_id 这些页面 JS 铸的指纹键
    正好是非 Secure ⇒ 改成 *:// + 裸域(三趟弯路记在 extension/README.md);
  3. 「点了同意进不去」 → POST /settings/agreement 少了 Content-Type: application/json,
    FastAPI 回 422,而错误提示把数组 detail 渲染成了 [object Object] —— 两处都修了,
    并补了"请求形状"用例(devlog/370);
  4. ui_probe --toolbar「向下滚工具条没让位」红了很久 → 尺子挑到了面板外面
    (侧栏也有 .os-scroll):产品无辜,探针修好后进了 A 档门禁(devlog/367)。

🔒 工程、安全与验证(维护者)

  • CI 落地(GitHub Actions):Linux 上后端(uv sync --frozen + pytest + 文档漂移门禁)
    与前端(tsc / eslint / vitest),Windows 上 Rust 单测 + sidecar 冒烟;
  • 安全:本机会话 token(壳生成 → 注入后端与前端,"开发态工具漏带 token"也一并堵上);
    平台 HTML 白名单净化后才进详情;命令准入与外链白名单;启动红框改成可导出的问题报告;
    数据目录迁移可回滚、旧目录全程不动,并给了安全删除入口;依赖只认锁文件;
  • 后端:平台适配层(BasePlatform + cursor 语义 + 四类失败语义 + 端点熔断 + 身份级限速)、
    调度生命周期可停止、事务边界的五条失败路径、文件与 SQLite 并发面收敛、
    消息由领域事件改走推送;
  • 前端:工具条显隐 / 筛选 / 分页 / 选定账号身份机 / 迁移编排都抽成了可注入的函数或 hook
    (迁移编排带四条回滚判据:任何一步失败都回退到原目录);
  • 门禁:A 档 15 步(含 5 个 UI 探针模式与扩展冒烟);scripts/release.py 一键发布;
  • 实测:后端 1229 条 / 前端单测 1073 条(81 个文件)/ 桌面壳 cargo test 64 条 /
    扩展 node --test 25 条;
  • 一条踩过的坑记在这:with TestClient(app, client=…) as c: 会跑 lifespan,
    把进程级"外部任务在跑"的状态泄漏给别的用例(8 条无关用例变红)——
    现在按仓库约定用 yield TestClient(app, client=("127.0.0.1", 51234))。

🚫 下线

  • 桌面悬浮胶囊小窗整条线(含"原生 Rust 重建"的方案与代码):2026-10-03 由你拍板彻底放弃,
    为什么放弃与当时的实测数据见 devlog/274。

📦 资产

  • DDtoolkit_1.1.0_x64-setup.exe — Windows NSIS 安装包(用户级安装)
  • DDtoolkit-portable-win64.zip — 便携版(解压即用,含后端 onedir)
  • latest.json + 安装包的 .sig — 应用内更新的载体与清单(手工下载请用上面两项)

数据目录:安装版默认 %APPDATA%\com.ddtoolkit.app;设了 DDTOOLKIT_DATA_DIR 就用它
(便携/自定义安装),也可以在「设置 → 关于」里迁移到其他盘。

⚠️ 升级说明

  • 数据库自动迁移 f004 → f009(置顶动态 / 档案卡布局 / 事件图标 / 头像账本 / 轻资产索引),
    首次启动会多等一会儿;覆盖安装即可,不需要手工操作;
  • 本版第一次引入使用须知 ⇒ 所有人都会在启动时遇到那一次确认;之后只有声明正文更新
    或新装才要确认;
  • 抖音默认关着:想抓抖音去「设置 → 抓取设置 → 平台抓取」打开(风险自担);
  • 档案视图暂时隐藏(没开发完),按钮与深链接一起收起来了;
  • 浏览器扩展要手工装一次(加载解压缩的扩展),装完在应用里复制配对 token;
  • v1.0.2 的行为不变:关闭窗口 = 隐藏到系统托盘、深休眠释放界面内存、数据目录迁移、
    应用内更新(签名校验 / 便携版不自动覆盖)。

🔧 技术栈

  • 后端:Python 3.14 + FastAPI + SQLAlchemy 2.0 + SQLite(WAL) + APScheduler + Alembic(迁移链 f009)
  • 前端:Vite + React 18 + TypeScript + Tailwind v4 + ECharts 6 + Radix
  • 桌面壳:Tauri v2(托盘 + 拉起后端 + 注入空闲端口 + Job Object 进程看门狗)
  • 浏览器扩展:MV3(纯 JS + chrome.cookies,无构建步骤)

⚖️ 许可

MIT License(见 LICENSE)。嵌入字体:阿里妈妈方圆体(官方许可免费商用 + 允许嵌入)。
抖音签名实现移植自 Douyin_TikTok_Download_API
(Apache-2.0:许可原文与上游 NOTICE 随仓库 app/services/platforms/vendor/dtksign/ 一起分发)。