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 带网关原话 / 正常返回)。
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>AgentOS Dashboard</title>
|
||||
<link rel="stylesheet" href="/src/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="sidebar" id="sidebar">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px">
|
||||
<h1 style="margin-bottom:0;cursor:pointer;font-size:14px" onclick="toggleSidebar()">🖥 AgentOS <span style="font-size:9px;margin-left:2px">v4</span></h1>
|
||||
<div onclick="toggleSidebar()" style="cursor:pointer;padding:2px 6px;border-radius:4px;font-size:12px;color:var(--text2);transition:.15s" title="折叠侧边栏" id="sidebarToggleBtn">◀</div>
|
||||
</div>
|
||||
<div id="identityBar" style="margin-bottom:12px;padding:6px 10px;background:var(--bg3);border-radius:8px;font-size:10px;color:var(--text2);line-height:1.6">
|
||||
<div id="identityHostname"></div>
|
||||
<div id="identityMeta" style="opacity:.7"></div>
|
||||
</div>
|
||||
<div id="navBar" class="nav"></div>
|
||||
<div style="flex:1"></div>
|
||||
<div style="padding:6px 0;display:flex;gap:4px">
|
||||
<div class="nav-item" onclick="collapseAllGroups()" style="flex:0;text-align:center;font-size:11px;padding:7px 6px" title="折叠全部">📂</div>
|
||||
<div class="nav-item" onclick="gitSync()" style="flex:1;text-align:center;font-size:11px">🔄 同步</div>
|
||||
<div class="nav-item" onclick="location.reload()" style="flex:1;text-align:center;font-size:11px">⟳ 刷新</div>
|
||||
</div>
|
||||
</nav>
|
||||
<main class="main" id="app">
|
||||
|
||||
<!-- Stats bar(默认隐藏,右侧小按钮可展开;用户反馈占地方影响操作) -->
|
||||
<div id="statsToggleWrap" style="display:flex;justify-content:flex-end;margin:0 0 2px">
|
||||
<button id="statsToggle" onclick="window.toggleStatsBar&&window.toggleStatsBar()"
|
||||
title="显示/隐藏顶部统计与机器状态"
|
||||
style="background:none;border:none;color:var(--text2);cursor:pointer;font-size:11px;
|
||||
padding:1px 6px;opacity:.55">📊 统计</button>
|
||||
</div>
|
||||
<div class="stats" id="statsBar" style="display:none"></div>
|
||||
<!-- Machine status bar -->
|
||||
<div id="machineBar" class="machines-bar" style="display:none"><span style="font-size:11px;color:var(--text2)">⏳ 加载机器状态...</span></div>
|
||||
<!-- Execution history -->
|
||||
<!-- execHistory 已迁移到指挥台视图 -->
|
||||
|
||||
<!-- ═══ 系统知识中心 ═══ -->
|
||||
<div id="view-kb" class="hidden">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px">
|
||||
<h2 style="font-size:18px">📚 系统知识中心</h2>
|
||||
<div style="display:flex;gap:6px">
|
||||
<button onclick="kbRefresh()" style="background:transparent;color:var(--text);border:1px solid var(--border);padding:6px 12px;border-radius:6px;cursor:pointer;font-size:12px">🔄 刷新</button>
|
||||
<button onclick="kbLoadLogs()" style="background:transparent;color:var(--text);border:1px solid var(--border);padding:6px 12px;border-radius:6px;cursor:pointer;font-size:12px">📋 日志</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex;gap:4px;margin-bottom:16px;flex-wrap:wrap">
|
||||
<div class="kb-tab active" data-tab="kb-knowledge" onclick="kbSwitchTab('kb-knowledge',this)">📖 知识库</div>
|
||||
<div class="kb-tab" data-tab="kb-memory" onclick="kbSwitchTab('kb-memory',this)">🧠 记忆库</div>
|
||||
<div class="kb-tab" data-tab="kb-system" onclick="kbSwitchTab('kb-system',this)">🤖 联邦系统说明</div>
|
||||
<div class="kb-tab" data-tab="kb-skills" onclick="kbSwitchTab('kb-skills',this)">🧩 技能与工具</div>
|
||||
</div>
|
||||
<div id="kb-tab-knowledge" class="kb-tab-body">
|
||||
<div id="kbStats" style="display:grid;grid-template-columns:repeat(auto-fill,minmax(110px,1fr));gap:8px;margin-bottom:12px"></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px">
|
||||
<div style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border)">
|
||||
<div style="font-size:13px;font-weight:600;margin-bottom:8px">⚡ 操作面板</div>
|
||||
<div style="display:grid;gap:6px">
|
||||
<button onclick="kbShowRefine()" style="text-align:left;background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:6px;cursor:pointer;font-size:12px">🧹 提纯收件箱</button>
|
||||
<button onclick="kbShowCollect()" style="text-align:left;background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:6px;cursor:pointer;font-size:12px">📥 汇聚到收件箱</button>
|
||||
<button onclick="kbShowIngest()" style="text-align:left;background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:6px;cursor:pointer;font-size:12px">📝 导入知识</button>
|
||||
<button onclick="kbShowSearch()" style="text-align:left;background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:6px;cursor:pointer;font-size:12px">🔍 搜索</button>
|
||||
<button onclick="kbShowBackup()" style="text-align:left;background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:6px;cursor:pointer;font-size:12px">💾 备份</button>
|
||||
<button onclick="kbGitSync()" style="text-align:left;background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:6px;cursor:pointer;font-size:12px">🔄 Git同步</button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border)">
|
||||
<div style="font-size:13px;font-weight:600;margin-bottom:8px">📋 参数 / 结果</div>
|
||||
<div id="kbResultPanel" style="font-size:12px;color:var(--text2)">点击操作设置参数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="kbLogs" style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border)"></div>
|
||||
</div>
|
||||
<div id="kb-tab-memory" class="kb-tab-body" style="display:none">
|
||||
<div id="memStats" style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:12px"></div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px">
|
||||
<div style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border)">
|
||||
<div style="font-size:13px;font-weight:600;margin-bottom:8px">🧠 记忆层级</div>
|
||||
<div style="display:flex;gap:4px;flex-wrap:wrap;margin-bottom:8px">
|
||||
<button onclick="memShowL1()" style="background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:6px 12px;border-radius:6px;cursor:pointer;font-size:11px">🔑 L1 关键词</button>
|
||||
<button onclick="memShowL2()" style="background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:6px 12px;border-radius:6px;cursor:pointer;font-size:11px">📋 L2 事实</button>
|
||||
<button onclick="memShowL3()" style="background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:6px 12px;border-radius:6px;cursor:pointer;font-size:11px">📄 L3 原文</button>
|
||||
</div>
|
||||
<div id="memContent" style="font-size:12px;color:var(--text2)">点击按钮查看各层详情</div>
|
||||
</div>
|
||||
<div id="memDetailPanel" style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border);overflow-y:auto;max-height:400px"><div style="font-size:13px;font-weight:600;margin-bottom:8px">📋 详情</div><div id="memDetailContent" style="font-size:12px;color:var(--text2)">选择左侧查看</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="kb-tab-system" class="kb-tab-body" style="display:none">
|
||||
<div style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border);margin-bottom:12px"><div style="font-size:13px;font-weight:600;margin-bottom:8px">🤖 联邦系统文档</div><div id="sysDocsList" style="font-size:12px;color:var(--text2)">加载中...</div></div>
|
||||
<div style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border)"><div style="font-size:13px;font-weight:600;margin-bottom:8px">📋 文档内容预览</div><div id="sysDocPreview" style="font-size:12px;color:var(--text2);max-height:400px;overflow-y:auto;white-space:pre-wrap;font-family:monospace">选择左侧文档查看</div></div>
|
||||
</div>
|
||||
<div id="kb-tab-skills" class="kb-tab-body" style="display:none">
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px">
|
||||
<div style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border)"><div style="font-size:13px;font-weight:600;margin-bottom:8px">🧩 已安装技能</div><div id="skillsList" style="font-size:12px">加载中...</div></div>
|
||||
<div style="background:var(--bg2);border-radius:10px;padding:12px;border:1px solid var(--border)"><div style="font-size:13px;font-weight:600;margin-bottom:8px">🔧 工具目录</div><div id="toolsList" style="font-size:12px">加载中...</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══ 登录管理(新建)═══ -->
|
||||
<div id="view-matrix-login" class="hidden"><div class="loading">⏳ 加载登录管理...</div></div>
|
||||
|
||||
<!-- ═══ 动态视图容器(供46个已迁移视图用)═══ -->
|
||||
<div id="view-dynamic" class="hidden"></div>
|
||||
|
||||
<!-- ═══ 蓝图执行弹窗 ═══ -->
|
||||
<div id="bpExecModal" style="display:none;position:fixed;inset:0;z-index:100;background:rgba(0,0,0,.7);align-items:center;justify-content:center" onclick="if(event.target===this)closeBpModal()">
|
||||
<div style="background:var(--bg2);border-radius:12px;padding:24px;max-width:500px;width:90%;max-height:80vh;overflow-y:auto" id="bpExecContent" onclick="event.stopPropagation()"></div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user