Files
douyin-pc/docs/2026-09-06-12-33-development-testing-delivery.md
T

13 KiB
Raw Blame History

Windows 多账号桌面应用:实现、验证与交付记录

1. 交付结论与边界

基准:2026-09-06-11-05-PLAN.md;业务决策:2026-09-06-11-24-implementation-decisions.md

已实现并构建 Windows x64 0.1.0 初版,仅向指定 Windows 机器发布。最终交付是一个中文安装程序,包含 Python、Qt/PySide6、Playwright 及其 Node 驱动、psutil、Chrome for Testing。普通使用者无需安装开发工具或下载运行环境。

没有执行产品安装程序,也没有自动登录、关注、私信或标记通知已读。 安装/卸载/覆盖升级的人工体验、多真实账号组合及真实写操作验收,仍由用户完成。不能将离线矩阵或只读线上验证表述为真实写操作已经验收。

Windows 桌面发布位置:

C:\Users\rogee\Desktop\抖音账号助手-0.1.0\
  DouyinAccounts-0.1.0-Windows-x64-Setup.exe
  SHA256SUMS.txt
  使用说明.txt

安装程序:234,266,549 字节(约 223.4 MiB)。

SHA256 bdbfb8a642092eb5775a94ca47b153d37a96e3819b74582b0633e0450e1a188f

目前未购买代码签名证书,可能出现未知发布者/SmartScreen 提示;不要以关闭系统防护作为安装步骤。

2. 已确认的业务语义

  • 规则在界面配置,默认关闭;配置通知类型、关注/私信、正文及关注成功后再私信。
  • 一条通知交给一个关联小号,组内轮询。不向所有小号广播。一条聚合通知内的多个有效来源用户,各产生相应步骤。
  • 小号最多归属一个大号。切换/解除时,在同一 SQLite 事务中检查执行中任务、取消旧组待执行任务并更新归属。
  • 执行中禁止切换;历史与 unknown 结果保留,不改派、不重发,不变更登录目录。
  • 小号失效时原任务等待;大号失效或监听连接不可用时整组暂停。
  • 停止只暂停领取和监听,并等待在途请求落库;保留 Chrome。关闭浏览器和删除登录数据是独立操作。
  • 保存上次启动所选组;软件打开不自动执行,用户需再次点击启动。
  • 修改规则不改写已有任务快照;关闭规则会暂停该组待执行任务。

3. 代码与实现落点

文件 职责
src/account_browser.py 独立目录/进程/端口;全局与单账号配置;官方 Chrome 优先、随包浏览器兜底;进程创建时间、命令行、CDP 监听归属验证;旧实例安全关闭;账号目录删除;单实例锁与目录权限
src/account_session.py 显式 loopback CDP 与期望 UID;唯一首页/自身页选择;实时自身身份核验;SDK 订阅及释放;通知详情;关注写前检查和写后核对;IM SDK 调用
src/account_store.py SQLite WAL/事务/外键;账号与规则;推送 ID inbox;事件去重;组内轮询;持久化任务、依赖与状态迁移;归属事务;unknown 人工确认
src/account_engine.py 单 asyncio 循环拥有运行状态与数据库连接;按账号监听/串行执行;组级暂停;重连恢复;停止等待;结果落库;脱敏滚动日志
src/accounts_app.py PySide6 中文窗口;大号分组与小号;头像、昵称、UID、登录/身份/运行状态;规则、切换、设置、关闭、删除;任务状态及全库计数;独立后台线程;安全退出;离线冒烟入口
src/cdp_explicit.py 独立脚本兼容传输层,要求明确 CDP 地址和期望 UID;不使用全局首个标签,不依赖 browser-harness
src/accounts_cli.py 打包后的 CLI 调度入口
src/test_accounts.py 离线存储/身份/组隔离/时序/结果分类测试
src/test_browser_matrix.py 真 Chrome、假站点数据的进程/CDP/存储/生命周期矩阵
build_windows.py / installer.iss Windows 原生 onedir、浏览器校验与收集、许可与清单、打包冒烟、中文单文件安装包

现有 get_current_user.pyget_notifications.pyfollow_user.pydouyin_im.pyverify_notification_mark_read.py 均接入显式 CDP 参数;订阅内部模块复用同一传输层。现有 CLI 仍可独立运行。订阅支持 --sub--subscribe

安全与持久化细节

  • 账号目录以随机内部 ID 命名,不以昵称、UID 或固定测试环境命名。不同浏览器可执行路径使用不同目录,不迁移 Cookie。
  • 只连接 http://127.0.0.1:端口 / localhost / IPv6 loopback;浏览器实际监听与进程归属也核验。
  • 高级参数使用小型允许列表;禁止覆盖端口、user-data-dir、关闭 web security/sandbox、加载扩展等破坏隔离的参数。
  • 重启时 running → unknown,绝不重发。关注超时尝试只读核对;无法确认仍 unknown。IM 缺失或不明确结果不按成功处理。
  • 私信任务可依赖前置关注。前置失败取消依赖任务;前置 unknown 等人工确认,不自行推进。
  • 小号在身份异步核验期间切换归属的竞态已加校验与专门回归测试。
  • 通知详情读取原始文本后由 Python 解 JSON,避免 JavaScript 丢失 64 位数字 ID 精度。
  • 日志仅保留内部账号 ID、任务 ID、动作、状态及安全错误;不记录消息正文、Cookie、token、签名 URL 或原始请求。
  • Windows 数据目录移除继承权限,授予当前用户与 SYSTEM;其他平台设为 0700。
  • 安装目录与数据目录分开。卸载脚本没有删除账号数据的逻辑;实际卸载体验仍待人工验证。

4. 自动验证证据

Linux 开发环境

uv venv .venv
uv pip install --python .venv/bin/python -r requirements-desktop.txt
uv tool run pyright --project pyrightconfig.json \
  src/account_store.py src/account_browser.py src/account_session.py \
  src/account_engine.py src/accounts_app.py src/accounts_cli.py \
  src/cdp_explicit.py src/test_accounts.py src/test_browser_matrix.py
.venv/bin/python -m unittest discover -s src -v
.venv/bin/python src/test_subscribe_notifications.py
QT_QPA_PLATFORM=offscreen .venv/bin/python src/accounts_app.py --smoke-test /tmp/douyin-linux-smoke-final.json
.venv/bin/python src/accounts_cli.py notifications --help

结果:配置化 Pyright 0 error / 0 warning22 项 unittest 通过;既有 Node SDK/通知桥检查通过;Qt/SQLite/Playwright 核心冒烟通过;CLI 帮助转发正确。

附加编辑器 LSP 曾持续误报 PySide6 与新同目录模块无法导入。已记录为环境/缓存误报;未以关闭实际类型检查代替验证。独立配置化 Pyright、Python 导入、Windows 打包执行均验证通过。部分辅助导入行保留窄范围 Pyright 缓存兼容注释。

Windows 原生源代码测试

构建工作目录:C:\Users\rogee\douyin-pc-build-20260906

  • Python 3.12 x64 原生构建。
  • 同一 22 项 unittest 通过
  • SDK/订阅桥检查通过。
  • 不启动业务、不创建真实账号的 GUI 源码冒烟通过。

Windows 真 Chrome 离线矩阵

使用随包 Chrome,而不是本机已登录浏览器;每次创建临时独立目录。所有 Douyin 页面/API 由 Playwright 路由返回固定假数据;浏览器首次 URL 也替换为 about:blank,零真实写操作。

通过项:

  1. 两个账号不同端口;
  2. 同一运行实例可核验并重连;
  3. 可在不依赖登录状态的情况下核验旧实例;
  4. 旧浏览器运行时配置变化被拒绝;
  5. 两个上下文的 UID 与 localStorage 隔离;
  6. 错误 UID 拒绝;
  7. 多个匹配标签拒绝;
  8. 浏览器运行时禁止删除登录目录;
  9. CDP 断开保留 Chrome
  10. 页面刷新后重新核验;
  11. 关闭、重启 Chrome 后 localStorage 保留;
  12. 只关闭自有实例,退出后能删除自己的目录。

测试中发现并修复了测试路由回调参数绑定、跨 CDP 连接关闭标签事件到达的时序,以及测试异常清理问题。最终矩阵全部通过,未将失败尝试记作成功。最终复查没有遗留 douyin-browser-test-* Chrome 进程。

Windows 打包验证

  • GUI onedir、CLI onedir 均原生 PyInstaller 构建成功;
  • 已收集 Python DLL、Qt DLL/plugins、Playwright Node 驱动、VC runtime DLL 和浏览器目录;
  • 打包 GUI 的 Qt/核心/SQLite/Playwright 冒烟通过,accounts=0、real_write_actions=0
  • 打包 CLI --help 通过;
  • 在 Windows 真实打包目录上,清空环境变量并模拟 frozen 入口,浏览器查找函数成功返回随包 Chrome(bundled-discovery-check.json);这是函数级检查,不冒充干净机器整包验收;
  • 中文与空格路径下,限制 PATH、设置无效外部 PYTHONHOME / PLAYWRIGHT_BROWSERS_PATH 的冒烟通过;
  • 所有 20 个 Python 源文件的本地 SHA256 与 Windows 发布清单一致;
  • Inno Setup 生成中文安装包成功,桌面副本 SHA256 与构建产物一致。

限制:不是重装的干净 Windows。 另做了两次通过环境变量隐藏系统 Chrome 的尝试,但程序仍选中系统 Chrome,未通过“实际走自动浏览器兜底”的该项断言,因此不将它记作空白系统测试通过。随包 Chrome 的真实运行已由上述离线矩阵独立验证;无系统 Chrome 的完整安装验收仍留给用户/干净虚拟机。

5. 线上只读验证

通过原有 localhost:9222 已登录浏览器开展,先使用 browser-harness 确认唯一自身页与真实登录。随后测试生产原生 CDP 接入:

  • 期望 UID 与自身接口返回一致;
  • 原生 Session 连接成功,官方网页通知 SDK 监听安装与卸载成功;
  • 读取 10 条通知成功;
  • 按一条通知 ID 读取详情成功;
  • 验证评论、点赞通知的来源用户字段形态;
  • 全程 0 次关注、0 次私信、0 次标记已读

未保存 UID、通知 ID、用户名、消息正文到本仓库验证文档;临时身份文件用 0600 并在结束时清理。

6. Windows 交付与构建依赖来源

优先检查 Windows MCP(可用),构建/批量命令使用 SSH,符合 ../windows/AGENTS.md。未把连接账号/地址写入运行时配置或安装包。

运行时锁定:

  • Playwright 1.55.0PySide6/shiboken6/Essentials/Addons 6.9.2psutil 7.0.0
  • greenlet 3.5.5pyee 13.0.1typing_extensions 4.16.0
  • Chrome for Testing 152.0.7977.82,官方 Google 分发,锁文件见 packaging/chrome-lock.json

构建:PyInstaller 6.15.0、hooks-contrib 2026.7;其余版本见 requirements-build-windows.txt

Inno Setup 6.7.3 从官方 jrsoftware/issrc GitHub release 下载;初始网站跳转所得文件未通过签名检查,未执行。正式 release 文件通过 Authenticode Valid 检查,发布者为 Pyrsys B.V.;再与 GitHub asset digest 核对,才安装构建工具。

https://github.com/jrsoftware/issrc/releases/download/is-6_7_3/innosetup-6.7.3.exe
SHA256 9c73c3bae7ed48d44112a0f48e66742c00090bdb5bef71d9d3c056c66e97b732

中文语言文件从官方仓库取得,保留版权/译者头:

https://raw.githubusercontent.com/jrsoftware/issrc/refs/heads/main/Files/Languages/ChineseSimplified.isl
SHA256 e0b0b350e2245f3c5e65586dfe43d574f6e7f06f2261149aba284954b3fc9a8d

语言文件摘要以本地文件 sha256sum packaging/ChineseSimplified.isl 为最终校验依据;源文件已随仓库保存,无需构建时再抓取最新翻译。

7. 未完成人工验收与已知限制

  • 多个真实大号/小号组合的登录、身份异常、SDK 账号兼容性和实际写请求;目前多账号矩阵使用假身份。
  • 安装、卸载、覆盖升级、SmartScreen、低权限/磁盘不足/杀毒误报等安装体验。
  • 完全无系统 Chrome、无预装开发/运行环境的干净 Windows 安装测试。
  • 用户必须先知道数字 UID;尚未提供“仅扫码即登记”的首次账号引导。
  • 页面刷新/断网期间尚未写入 inbox 的推送可能丢失;已写入的 ID 会恢复补取详情。没有宣称零丢事件或全历史自动回补。
  • SDK 内部对象仍依赖平台实现;结构变化会暂停,而不是绕过身份核验或盲目发送。
  • 本版同一 UID 只能登记一次。任务界面显示最近 500 条,计数覆盖数据库全部任务。
  • CLI 与桌面应用不应同时对同一账号进行写操作;CLI 不加入桌面的队列事务。
  • 数据保存在本机,不做跨 Windows 用户的 Cookie 解密迁移。后续数据库结构变更需要另写迁移,不代表任意未来版本都已验证兼容。

8. 过程状态

开始分支 main,基准提交 2389d9c7b68e85bc3d3fdba481be8f0066375ba5,初始工作区干净。先尝试后台开发/审查工作流,但 pi 安装缺少后台 server/client 依赖,工作流 6d397511-d446-4cba-8033-793199c7b315 未能启动子任务,未产生代码。已向用户报告并获得“当前会话直接完成”的明确许可,之后未切换到其他外部代理。

最终代码未经 git commit;保留全部改动供用户审阅。没有伪称独立子代理审查成功。本文件记录自审、自动化测试及实际发布证据。