Files
MediaCrawler/mac-agent-os-main/PLANS/REFORM_ANALYSIS.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

9.2 KiB
Raw Blame History

改造分析报告:现状 vs 目标架构

日期: 2026-07-04 | 基于 PLANS/TASK_ORCHESTRATION_ARCHITECTURE.md 审计范围: 全部 7 个模块,逐项检查


一、改造项总览

# 模块 改造类型 优先级
1 scheduler.py 🔧 重写 — 现有逻辑不满足需求 P0
2 priority_queue.py ✅ 不动 — 现有类直接可用 -
3 command_bus.py 🆕 新增 smart_comment 类型 P1
4 video_analyzer.py 🆕 新建 — 不存在 P1
5 corpus.py 🔧 改造 — 加行业过滤 + 万能兜底 P1
6 douyin.yaml 🔧 重构 — 语料分层 P1
7 profiles.json 🔧 补字段 — 加 industry P2
8 ops-command.js 🆕 加功能 — 三队列显示 P3

二、逐项分析


改造项 1:scheduler.py — 🔧 重写

当前代码(guardd/modules/scheduler.py:33-362):

当前是单队列模式:

class Scheduler:
    def __init__(self):
        self.queue = PriorityQueue()        # ← 一个队列装所有优先级
        self.active_tasks: dict[int, dict]  # {slot_id: task}
        self.paused_tasks: dict[int, dict]
功能点 现状 目标 问题
队列数量 1 个 混装所有优先级 3 个 独立队列(P0/P1/P2) ❌ P0不能插队,P2不能填空
_pop_next_task() 遍历所有任务,按(priority, scheduled_at)排序后取第一个 先看P0→再看P1→再看P2,且跳过 busy 账号 ❌ 无法实现优先级隔离
账号互斥 slot_manager.find_account() 在分配时检查 三层检查:入队时+分配时+执行前 ❌ 入队层不检查,可能重复入队
账号状态表 无 account_slots: dict[str, int] ❌ 没有快速查询账号状态的能力
P0 抢占 无 当前任务结束后插队 ❌ 完全未实现
P2 劣后 无 只在空闲时执行,可被抢占 ❌ 完全未实现
暂停任务暂存 paused_tasks 存在但不被 active 使用 P0插入时暂停P1,完成后恢复 ❌ 逻辑不完整

改造原因:当前逻辑是功能错误的。三个优先级的任务混在一个队列里,虽然排序时按 priority 字段,但 _pop_next_task 取完第一个任务后就 break 了,不会继续往后看。当高优任务 due 时间还没到时(scheduled_at > now),堆顶返回 None,整个调度循环就停了。这导致 P0 任务无法真正插队。

改动量:~200行,重写 Scheduler 类。


改造项 2:priority_queue.py — ✅ 不动

当前代码(guardd/modules/priority_queue.py:1-79):

class PriorityQueue:
    """基于 heapq 实现,支持优先级排序 + 时间调度 + 取消/重排"""

当前实现完全满足需求。三队列只需创建三个独立实例:

self.queue_priority = PriorityQueue()  # P0
self.queue_normal   = PriorityQueue()  # P1
self.queue_filler   = PriorityQueue()  # P2

无需修改此类。


改造项 3:command_bus.py — 🆕 新增 smart_comment

当前代码(services/command_bus.py:807-842):

CMD_REGISTRY = {
    "nurture": {...},
    "collect": {...},
    "login": {...},
    "logout": {...},
    "comment": {...},
    "like": {...},
    "interact": {...},
    "record": {...},
}
功能点 现状 目标 问题
评论类型 comment / interact — 直接传 mc task comment + smart_comment — 先分析视频再评论 ❌ 缺少视频分析环节
分发逻辑 按机器分组后直接发到 guardd 先调 VideoAnalyzer 分析所有URL,再分组分发 ❌ 无分析环节

改造原因:新功能需求。现有 comment/interact 可以保留不变,新增 smart_comment 走新的视频分析流程。

改动量:~20行,加一条注册表 + dispatch 分支。


改造项 4:video_analyzer.py — 🆕 新建

当前:文件不存在。

需要新建一个完整的视频分析模块,包含:

  • 浏览器打开 URL 提取标题/描述
  • 关键词匹配行业分类
  • 根据账号 industry 选评论

改造原因:完全是新增功能,原来是直接传评论或者随机取语料,现在需要先分析视频内容再做匹配。

改动量:~150行新文件。


改造项 5:corpus.py — 🔧 改造

当前代码(scripts/mc/corpus.py:51-57):

KEYWORD_CATEGORY_MAP = [
    (["科技", "数码", "手机"], ["称赞", "提问"]),
    (["美食", "做饭", "菜"], ["称赞", "共鸣"]),
    (["旅游", "风景", "旅行"], ["称赞", "提问"]),
    (["情感", "生活", "感悟"], ["共鸣", "安慰"]),
    (["知识", "科普", "教育"], ["提问", "补充"]),
]
功能点 现状 目标 问题
关键词覆盖 5组(科技/美食/旅游/情感/知识) 9+组(加上医疗/财经/育儿/汽车等) ❌ 无医疗关键词,健康类视频无法匹配
行业过滤 无 根据账号 industry 过滤语料 ❌ 医疗账号可能发科技评论
万能兜底 _get_random_comment() 全域随机 从万能池(称赞/提问/共鸣)取 ❌ 没有万能池概念
分类→方向映射 DIRECTION_TO_CATEGORY 5个 同步扩展 ❌ 需要对齐

改造原因:现有功能不完整。关键词覆盖太窄,缺少行业过滤机制和万能兜底逻辑。

改动量:~50行,改 KEYWORD_CATEGORY_MAP + get_comment_for_video()。


改造项 6:douyin.yaml — 🔧 重构

当前结构(corpus/douyin.yaml:239行):

categories:
  赞美:    (30条,通用)
  共鸣:    (15条,通用)
  提问:    (15条,通用)
  感慨:    (15条,通用)
  客观:    (10条,通用)
  补充:    (5条,通用)
功能点 现状 目标 问题
语料分层 平铺,都在同一层 两层:万能池 + 行业池 ❌ 无法区分行业
accessible 字段 无 accessible: "*" 或 accessible: ["health"] ❌ 无法限制账号使用
match_tags 字段 无 每个行业池带关键词标签 ❌ 无法自动匹配视频

改造原因:结构设计不满足新需求。需要按行业分层,加 accessible 和 match_tags 字段。

改动量:YAML 结构调整,将现有评论分类到"万能称赞""万能提问""万能共鸣"下,新增"大健康称赞"等行业池。


改造项 7:profiles.json — 🔧 补字段

当前(profiles.json:344行):

{
  "douyin_133": {"nickname":"苏州胃肠体检敏敏", ...},
  "douyin_test": {"nickname":"小美养生茶", ...},
}

没有一个账号有 industry 字段。

改造原因:缺少关键数据。没有 industry 字段,VideoAnalyzer 无法判断账号该用哪个语料池。

改动量:每个账号加一行 "industry": "health" 或 "industry": "general",手动配置。


改造项 8:ops-command.js — 🆕 加功能

当前代码:

前端已有 P0/P1/P2 的 HTML 筛选 checkbox(第41-43行),但后台 scheduler 返回的队列数据中优先级是混在一起的,前端无法真正按优先级分类展示。

改造原因:新功能需求。后台改为三队列后,前端需要分开显示三个队列的长度+内容。

改动量:~80行,加三个队列的独立展示区域。


三、改造原因分类

类别 数量 项
❌ 功能错误(现有逻辑有问题) 1 scheduler.py — 单队列导致P0/P2无法正常工作
⚠️ 功能不完整(有但不够) 2 corpus.py 关键词覆盖窄、douyin.yaml 无行业过滤
🆕 新功能需求(完全新增) 4 video_analyzer.py、command_bus smart_comment、profiles.json industry、ops-command三队列
✅ 无需修改 1 priority_queue.py

四、按 Phase 的改造详细清单

Phase 1:队列改造(P0)

文件 当前行数 改动 原因
guardd/modules/scheduler.py 362行 重写:单队列→三队列 + 账号互斥表 + P0抢插 + P2填空 ❌ 功能错误,当前单队列无法实现优先级隔离

Phase 2:语料重组(P1)

文件 当前行数 改动 原因
corpus/douyin.yaml 239行 重构为万能池+行业池 🆕 新需求,需要按行业分层
scripts/mc/corpus.py 701行 扩展关键词 + 加行业过滤 + 万能兜底 ⚠️ 关键词覆盖窄,缺少过滤
profiles.json 344行 各账号加 industry 字段 🆕 新需求,需要标记账号行业

Phase 3:视频分析(P1)

文件 当前行数 改动 原因
新建 services/video_analyzer.py 0 → ~150行 视频URL分析+分类+选评论 🆕 完全新增
services/command_bus.py 1289行 CMD_REGISTRY 加 smart_comment 🆕 新需求

Phase 4:指挥台展示(P2)

文件 当前行数 改动 原因
frontend/views/ops-command.js 413行 三队列独立展示 🆕 新需求