Files
MediaCrawler/mac-agent-os-main/archive_docs/matrix_docs/REFACTOR-PLAN.md
T
butubb 2112c1a870
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s
feat(monitor): 抖音 Web 接口客户端 —— 绕开爬虫子进程,直接发 HTTP
移植自 mac-agent-os 的 mediacrawler_adapter:不起子进程、不开页面,用浏览器里那份
登录态直接调抖音 Web 接口。产物键名照抄 store/douyin,所以 ingest 那条链路一个字不用改。

**目前能用的(真环境实测,非推断)**:

    profile/other : 200, 7075 字节  —— 博主主页指标(粉丝/获赞/作品数/昵称)
    aweme/detail  : 200, 45425 字节 —— 单条作品详情(含点赞/评论/收藏/分享)

**目前不能用的:作品列表 `aweme/post`。** 两个互相独立的原因:
  1. 这个接口被抖音单独升级成了真校验:不带 x-tt-argus 回 403「Uifid Not Found」,
     带上 dummy 值回 200 + **空 body**。也就是说「头在不在」骗得过,「真校验」过不了。
     同一套头打 profile/other 和 aweme/detail 都是通的 —— 抖音是挑着接口加保护的,
     挑中的恰好是「批量拉作品列表」这个最敏感的动作。
  2. 改走页面截获也不行:CDP 浏览器打开博主主页会落到「验证码中间页」(当天大量探测的
     代价,过几小时要重测)。

  所以现在的边界是:**已知作品的指标刷新能做,自动发现新作品做不了**。

**排查中控住变量后得到的两条事实**(都写进注释了):
  · `Accept` / `Accept-Language` / `Referer` 才是主页接口能返回真数据的原因 —— 只有
    UA+client hints+Cookie 时是 200 但仅 121 字节的空壳,补上这三个头变 7074 字节。
    (我先前猜的 sec-ch-ua 不是关键。)
  · 因此 UA 与 client hints 必须**成套地取自同一个浏览器**,所以 BrowserIdentity 一次
    从 CDP 取齐 cookie + UA + hints,而不是各自写死。

「200 + 空 body 必须当场报错」也是刻意写死的:放过去它会在下游变成「这个博主没作品」,
把一次失败伪装成一条正常结果 —— 爬虫那条路正是这么栽的,还被翻译成「账号被封」。

测试 +11:cookie 解析、请求头成套性(含 uifid 缺失/回退)、产物键名与 store 对齐、
以及 _get 的三条失败路径(空 body / 403 带网关原话 / 正常返回)。
2026-10-10 17:12:25 +08:00

6.2 KiB

Matrix 养号系统 — 重构设计方案 v2.2

最后更新:2026-05-01 版本:2.2.0 (草案)

本文件为设计方案,待确认后再实施。

一、当前问题诊断

# 问题 根因 影响
1 退出时 Chrome 崩溃/恢复弹窗 os.kill(pid, 9) 强行杀进程,未走正常关闭 下次启动弹恢复确认框
2 点赞/收藏永远失败 操作前未验证当前页面状态,直接在首页点按钮 操作无效果
3 "11/11 完成"但什么都没做 没有操作后的锚点验证,异常也被吞了 误报成功
4 不知道当前在什么页面 没有页面状态跟踪器 操作错位
5 登录验证不可靠 只查了一个 data-e2e 选择器,页面不同状态结果不同 误判未登录
6 脚本散乱不可组合 每个测试脚本都重复写类似逻辑 维护成本高

二、架构设计

2.1 三层架构

┌─────────────────────────────┐
│    WorkBuddy 技能层          │  ← 对话触发
│  (SKILL.md + 养号指令)       │
├─────────────────────────────┤
│    orchestrator 调度层       │  ← 智能选账号/蓝图/状态机
│  (yanghao_orchestrator.py)  │
├─────────────────────────────┤
│    原子操作层 (21个原子操作)   │  ← 可组合、可验证
│  (AtomOps + 校验器)          │
├─────────────────────────────┤
│    CDP连接器 + 浏览器管理     │  ← 优雅启停
│  (cdp_connector + browser)  │
└─────────────────────────────┘

2.2 原子操作定义 (每个操作带前置校验 + 后置锚点)

每个原子操作 = (名称, 执行函数, 前置校验, 后置锚点, 超时, 重试次数)

例子:
  "like" =
    pre_check:  当前在视频播放器页, 点赞按钮存在
    execute:    点击 [data-e2e="video-player-digg"]
    post_check: 点赞数+1 或 按钮状态变化
    timeout:    10s
    retry:      2次

2.3 页面状态机

[首页 grid] ──点击视频──→ [视频播放器]
    ↑                       │
    │                       ↓
    │                   [下滑/下一条]
    │                       │
    │                       ↓
    │                   [新视频播放器]
    │                       │
    └─────── 返回首页 ──────┘

页面锚点:
  grid 模式:  有 [data-e2e="alink-item"],无 video-player-digg
  播放器模式: 有 [data-e2e="video-player-digg"]
  搜索页:     有 [data-e2e="searchbar-input"]
  登录态:     有 sessionid cookie + 特定 DOM 元素

2.4 浏览器优雅管理

# 不要 kill -9,用正常关闭
browser_manager = BrowserManager()
await browser_manager.launch(account='douyin_01')  # 启动
await browser_manager.close()                       # 正常关闭,不走 kill
await browser_manager.graceful_shutdown()           # 先 SIGTERM,等待,再 SIGKILL

2.5 蓝图新格式 (带验证锚点)

{
  "id": "douyin_browse_v2",
  "version": "3.0.0",
  "steps": [
    {
      "step_id": 1,
      "op": "goto_and_verify",
      "args": {"url": "https://www.douyin.com/"},
      "verify": {"mode": "page", "anchor": "alink-item"},
      "on_fail": "retry(2)"
    },
    {
      "step_id": 2,
      "op": "open_video",
      "args": {},
      "verify": {"mode": "element", "selector": "[data-e2e='video-player-digg']"},
      "on_fail": "try_search"
    },
    {
      "step_id": 3,
      "op": "wait_watch",
      "args": {"seconds": 8},
      "verify": {"mode": "state", "field": "video_playing", "expect": true},
      "on_fail": "skip"
    },
    {
      "step_id": 4,
      "op": "like",
      "args": {},
      "verify": {"mode": "change", "selector": "[data-e2e='video-player-digg']", "attr": "class"},
      "on_fail": "log_warn"
    }
  ]
}

2.6 调度器设计

class YanghaoOrchestrator:
    """养号调度器"""
    
    async def run(self, account_id, blueprint_id):
        """执行一次养号"""
        # 1. 校验账号配置
        # 2. 校验蓝图
        # 3. 启动浏览器 (优雅)
        # 4. 登录校验
        # 5. 逐步骤执行 (带验证锚点)
        # 6. 生成报告
        # 7. 关闭浏览器 (优雅)
    
    async def verify_login(self):
        """多维度验证登录态"""
        # cookie: sessionid 存在
        # DOM: user-avatar 或 user-detail 可见
        # 请求: 能获取推荐内容

2.7 接入 WorkBuddy 技能

在 matrix/SKILL.md 中新增触发词:

triggers:
  - 养号
  - 运行养号
  - 南方小马铃薯
  - 次元时空的桃子
  - 橙子哥

WorkBuddy 通过 Skill 工具加载后,由我在对话中根据你的指令自动编排执行,而不是写死脚本。

2.8 接入 agentos CLI

agentos yanghao                             # 交互选账号+蓝图
agentos yanghao --account douyin_01         # 指定账号
agentos yanghao --account douyin_01 --blueprint douyin_browse_v2  # 全指定
agentos yanghao --list                      # 列出账号和蓝图
agentos yanghao --status                    # 查看当前运行状态

2.9 跨机恢复

agent-sync/02_skills/matrix/  →  包含所有脚本和蓝图
agent-local/tools/matrix/     →  账号登录态、Cookies、Profiles

换机流程:
  agentos init                    → 安装技能+目录
  agentos restore backup.tar.gz   → 还原登录态
  agentos yanghao --status        → 验证可用

三、实施计划(建议)

  1. 阶段1: 设计并实现 AtomOps 原子操作层(含前置校验+后置锚点)
  2. 阶段2: 实现 BrowserManager 优雅启停
  3. 阶段3: 实现 PageState 页面状态机
  4. 阶段4: 重写蓝图格式(v3.0.0),加入验证锚点
  5. 阶段5: 实现 YanghaoOrchestrator 调度器
  6. 阶段6: 接入 agentos CLI 和 WorkBuddy 技能
  7. 阶段7: 全面测试三账号 + 跨机恢复