Files
MediaCrawler/mac-agent-os-main/archive_docs/matrix_docs/REFACTOR_PLAN_v5.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

8.1 KiB
Raw Blame History

Matrix 重构方案 v5 — 执行可靠性 + 智能体可调用

版本: v5.0 | 日期: 2026-06-09 | 状态: 方案阶段 基于: 全项目代码审查 + AgentOS 联邦架构理解


一、目标

让 Matrix 养号系统达到三个标准:

  1. 执行可靠性 — 每个操作有前后验证,结果可追踪,不误报成功
  2. 智能体可稳定调用 — 统一的 CLI + 清晰的文档,智能体不需要读源码就能用
  3. 自动化任务 — 通过 guardd 或 cron 定时执行,不依赖人工盯日志

二、当前问题根因

核心矛盾:engine.py 的 run_single() (773行) 是一艘"独木舟"——
自己解析蓝图、自己连浏览器、自己写 page.evaluate 执行操作、自己汇总报告。
它绕过了系统里已有的 DouyinOps (563行) 和 AtomOps (517行),
把调度层和操作层糊在一起,导致:

  → 操作执行后无验证 (like 按钮真的变色了吗?)
  → 小红书操作零抽象 (10个 xhs_* 全是内联 evaluate)
  → 新增平台/操作需要修改 engine.py 本身
  → 测试一个操作 = 启动整个引擎

三、目标架构

mc (唯一 CLI 入口)
  │
  ├─ mc run → mc/engine.py (纯调度层, ~200行)
  │   │
  │   ├─ 解析参数 (accounts, blueprints, rounds)
  │   ├─ 并行调度 (asyncio.gather, 每账号一个持久浏览器)
  │   ├─ 蓝图选择 (_pick_blueprint)
  │   └─ 报告汇总 (BatchReport)
  │       │
  │       └──→ platform_ops/ (平台操作层, 每平台一个类)
  │            ├── DouyinOps   — 已有 (douyin_ops.py)
  │            ├── XhsOps      — 新建 (从 engine.py 提取)
  │            ├── ProfileReader — 新建 (dy_read_* 系列)
  │            └── AtomOps     — 已有, 集成 pre_check/post_check
  │
  ├─ mc account → matrix_mgmt.py (账号管理)
  ├─ mc blueprint → matrix_mgmt.py (蓝图管理)
  ├─ mc corpus → mc/corpus.py (语料库)
  └─ mc status → mc/status.py (状态查询)

四、执行链路重构

现状 (engine.py run_single)

if op == "goto_home":     ... conn.page.goto("https://www.douyin.com/") ...
elif op == "like":        ... conn.page.evaluate("querySelector...click()") ...
elif op == "xhs_like":    ... conn.page.evaluate("querySelector...click()") ...  # 又写一遍
elif op == "post_comment": ... pbcopy + evaluate + keyboard.press ...
# 28 个 elif...

目标 (调度器调用平台Ops)

async def run_single(self, account_id, blueprint_name, round_idx, conn=None):
    ops = PlatformOps.for_account(account_id, conn.page)
    
    for step in blueprint.steps:
        result = await ops.execute(
            op=step.op,
            args=step.args,
            validate=True              # ← 新增:执行后验证
        )
        report.add_step(result)

平台Ops 接口

class PlatformOps(ABC):
    """平台操作基类 — 智能体通过 mc 调用,不直接操作此类"""
    
    async def execute(self, op: str, args: dict, validate: bool = True) -> OpResult:
        """执行一个操作,可选验证"""
        
    def supported_ops(self) -> list[str]:
        """返回支持的操作列表"""

每个平台类(DouyinOps, XhsOps)实现此接口。对于已验证的操作(like, collect, comment等),内部委托给 AtomOps 以复用 pre_check/post_check。


五、操作验证机制

复用 atom_ops.py 中已有的 _execute() 模式:

操作执行流程 (每个步骤):
  1. pre_check() — 确认页面状态允许此操作
     ├─ like: 在视频播放器页? → check "video_player" 锚点
     ├─ comment: 评论区已打开? → check "comment_input" 锚点
     └─ goto_home: 总是允许
     
  2. execute() — 执行操作
     
  3. post_check() — 确认操作生效
     ├─ like: 按钮 class 变化?
     ├─ collect: 按钮状态切换?
     └─ goto_home: 页面加载完成?
     
  4. 失败重试 (默认1次)
  
  5. 返回结构化 OpResult { success, op, detail, elapsed, retries }

验证结果的存储

操作结果不在 print log 中散落,而是写入结构化记录:

# engine.py 回调 → 写 RunLog
class RunLog:
    account_id: str
    blueprint: str
    round: int
    steps: list[OpResult]
    started_at: datetime
    ended_at: datetime
    summary: {"success": 8, "failed": 2, "skipped": 1}

存储位置:agent-local/tools/matrix/logs/run_{date}_{account}.jsonl


六、新增文件清单

文件 来源 说明
scripts/ops/xhs_ops.py 新建 小红书操作(从 engine.py 提取 10 个 xhs_* 操作)
scripts/ops/profile_reader.py 新建 主页信息采集(dy_read_* / xhs_read_* 系列)
scripts/ops/_base.py 新建 PlatformOps 基类 + OpResult 定义
scripts/mc/runlog.py 新建 结构化运行日志
scripts/mc/nurture_daily.py 新建 Python版每日养号编排(替代 nurture_daily.sh 对 mc 的命令行调用)

七、修改文件清单

文件 变更
scripts/mc/engine.py 从 773行 缩至 ~250行,去除全部内联 page.evaluate,改为调用 PlatformOps
scripts/mc/cli.py 补全子命令(account create, status accounts),支持 --validate flag
scripts/mc/run.py 简化,委托 engine.BatchEngine
scripts/douyin_ops.py 实现 PlatformOps 接口,集成 AtomOps 验证
mc (shell wrapper) Python路径改为 which python3,去掉硬编码
scripts/nurture_daily.sh 改为调用 mc run 命令
SKILL.md 更新命令示例,文档状态
TOOL.md 版本号统一,架构图更新

八、文件废弃/归档

文件 处理
scripts/matrix.py 保留但加废弃说明,所有调用改用 mc
scripts/nurture_master.sh 废弃,功能由 nurture_daily.sh 覆盖
25+ 调试/测试脚本 移入 scripts/_archive/
scripts/yanghao_runner.py 交互模式合并到 mc account login
scripts/task_engine.py 蓝图执行功能合并到 mc/engine.py
scripts/matrix_modules/nurture/runner.py 废弃(1946行,功能被新engine覆盖)
scripts/camoufox_manager.py / camoufox_server.py 移入 _archive/
scripts/browser_manager.py / browser_keepalive.py 保留 mc/browser.py,删除重复

九、硬编码修复

位置 当前 修复
mc shell wrapper /Users/5kecheng/.workbuddy/... which python3 或 $AGENTOS_PYTHON
matrix_mgmt.py L32 /Users/chengzige/.workbuddy/... Path.home() / ".workbuddy"
nurture_master.sh 硬编码 Python 路径 改用 mc 命令
ARCHITECTURE.md L190 窗口位置硬编码 从 accounts.yaml 读

十、实施顺序

Phase 0 (本文档)                    [完成] 方案设计
Phase 1: 操作层提取                  [下一步]
  1. 创建 ops/_base.py (OpResult + PlatformOps 基类)
  2. 创建 ops/xhs_ops.py (从 engine.py 提取)
  3. 创建 ops/profile_reader.py (从 engine.py 提取)
  4. douyin_ops.py 实现 PlatformOps 接口

Phase 2: 引擎重构
  1. engine.py 从 773行 缩至 ~250行
  2. run_single() 改为调用 PlatformOps.execute()
  3. 集成 runlog.py 结构化日志
  4. 验证:用现有账号跑一次养号,确认结果一致

Phase 3: CLI 统一
  1. mc 补全缺失子命令 (account create, status)
  2. mc shell wrapper 修复硬编码路径
  3. 编写 mc 命令参考手册

Phase 4: 脚本清理
  1. 25+ 脚本移入 _archive/
  2. 废弃文件移除
  3. .gitignore 更新

Phase 5: 文档
  1. SKILL.md / TOOL.md / MODULE.md 更新
  2. 所有版本号统一为 v5.0

十一、不破坏的约束

  • agent-local/ 不动(本机数据,不同步)
  • cross_machine/data/matrix/ 不动(联邦状态通道)
  • blueprints/ 不动(共享蓝图,格式不变)
  • accounts_registry.yaml 不动
  • install.sh 不动(新机部署依赖它)
  • accounts.yaml 格式不动
  • 所有 shell 脚本的调用接口保持兼容(nurture_daily.sh 仍然可用)