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,113 @@
|
||||
# Matrix 养号系统全面测试报告
|
||||
|
||||
> **测试时间**: 2026-04-30 16:48:37
|
||||
> **测试蓝图**: douyin_browse_v2, douyin_search_browse
|
||||
> **测试账号**: douyin_01, douyin_02
|
||||
|
||||
---
|
||||
|
||||
## 测试总览
|
||||
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 总测试数 | 4 |
|
||||
| 通过数 | 0 |
|
||||
| 失败数 | 4 |
|
||||
| 通过率 | 0% |
|
||||
|
||||
## 按账号汇总
|
||||
|
||||
| 账号 | 蓝图 | 登录 | 步骤通过 | 总步骤 | 耗时 | 结果 |
|
||||
|------|------|------|---------|--------|------|------|
|
||||
| douyin_01 | douyin_browse_v2 | ❌ | 7 | 11 | 104.6s | ❌ |
|
||||
| douyin_01 | douyin_search_browse | ❌ | 4 | 7 | 78.6s | ❌ |
|
||||
| douyin_02 | douyin_browse_v2 | ❌ | 8 | 11 | 113.0s | ❌ |
|
||||
| douyin_02 | douyin_search_browse | ❌ | 6 | 7 | 76.7s | ❌ |
|
||||
|
||||
## 详细步骤结果
|
||||
|
||||
### douyin_01 / douyin_browse_v2
|
||||
|
||||
| 步骤 | 操作 | 参数 | 结果 | 耗时 | 错误 |
|
||||
|------|------|------|------|------|------|
|
||||
| 1 | goto_home | {} | ❌ | 28000ms | 视频加载超时 |
|
||||
| 2 | wait_watch | {'seconds': 8} | ✅ | 8000ms | |
|
||||
| 3 | like | {'probability': 0.4} | ❌ | 100ms | DouyinOps.like() got an unexpected keyword argument 'probability' |
|
||||
| 4 | next_video | {} | ✅ | 4000ms | |
|
||||
| 5 | wait_watch | {'seconds': 12} | ✅ | 12000ms | |
|
||||
| 6 | collect | {'probability': 0.15} | ❌ | 100ms | DouyinOps.collect() got an unexpected keyword argument 'probability' |
|
||||
| 7 | next_video | {} | ✅ | 4000ms | |
|
||||
| 8 | wait_watch | {'seconds': 10} | ✅ | 10000ms | |
|
||||
| 9 | like | {'probability': 0.3} | ❌ | 100ms | DouyinOps.like() got an unexpected keyword argument 'probability' |
|
||||
| 10 | next_video | {} | ✅ | 4000ms | |
|
||||
| 11 | wait_watch | {'seconds': 15} | ✅ | 15000ms | |
|
||||
|
||||
### douyin_01 / douyin_search_browse
|
||||
|
||||
| 步骤 | 操作 | 参数 | 结果 | 耗时 | 错误 |
|
||||
|------|------|------|------|------|------|
|
||||
| 1 | goto_home | {} | ✅ | 12000ms | |
|
||||
| 2 | search | {'keyword': '${SEARCH_KEYWORD}'} | ❌ | 7000ms | SEARCH_KEYWORD 未替换,搜索无效 |
|
||||
| 3 | click_search_result | {'index': 0} | ❌ | 3000ms | 不在搜索结果页 |
|
||||
| 4 | wait_watch | {'seconds': 10} | ✅ | 10000ms | |
|
||||
| 5 | like | {'probability': 0.5} | ❌ | 100ms | DouyinOps.like() got an unexpected keyword argument 'probability' |
|
||||
| 6 | go_back | {} | ✅ | 5000ms | |
|
||||
| 7 | goto_home | {} | ✅ | 13000ms | |
|
||||
|
||||
### douyin_02 / douyin_browse_v2
|
||||
|
||||
| 步骤 | 操作 | 参数 | 结果 | 耗时 | 错误 |
|
||||
|------|------|------|------|------|------|
|
||||
| 1 | goto_home | {} | ✅ | 30000ms | |
|
||||
| 2 | wait_watch | {'seconds': 8} | ✅ | 8000ms | |
|
||||
| 3 | like | {'probability': 0.4} | ❌ | 100ms | DouyinOps.like() got an unexpected keyword argument 'probability' |
|
||||
| 4 | next_video | {} | ✅ | 4000ms | |
|
||||
| 5 | wait_watch | {'seconds': 12} | ✅ | 12000ms | |
|
||||
| 6 | collect | {'probability': 0.15} | ❌ | 100ms | DouyinOps.collect() got an unexpected keyword argument 'probability' |
|
||||
| 7 | next_video | {} | ✅ | 4000ms | |
|
||||
| 8 | wait_watch | {'seconds': 10} | ✅ | 10000ms | |
|
||||
| 9 | like | {'probability': 0.3} | ❌ | 100ms | DouyinOps.like() got an unexpected keyword argument 'probability' |
|
||||
| 10 | next_video | {} | ✅ | 4000ms | |
|
||||
| 11 | wait_watch | {'seconds': 15} | ✅ | 15000ms | |
|
||||
|
||||
### douyin_02 / douyin_search_browse
|
||||
|
||||
| 步骤 | 操作 | 参数 | 结果 | 耗时 | 错误 |
|
||||
|------|------|------|------|------|------|
|
||||
| 1 | goto_home | {} | ✅ | 23000ms | |
|
||||
| 2 | search | {'keyword': '${SEARCH_KEYWORD}'} | ✅ | 9000ms | |
|
||||
| 3 | click_search_result | {'index': 0} | ✅ | 6000ms | |
|
||||
| 4 | wait_watch | {'seconds': 10} | ✅ | 10000ms | |
|
||||
| 5 | like | {'probability': 0.5} | ❌ | 100ms | DouyinOps.like() got an unexpected keyword argument 'probability' |
|
||||
| 6 | go_back | {} | ✅ | 3000ms | |
|
||||
| 7 | goto_home | {} | ✅ | 12000ms | |
|
||||
|
||||
## 问题分析与改进建议
|
||||
|
||||
| 严重度 | 类别 | 账号 | 问题 | 改进建议 |
|
||||
|--------|------|------|------|---------|
|
||||
| P1 | 登录 | douyin_01 | douyin_01 未登录,部分互动操作可能受限 | 手动登录该账号,或使用 --export-cookies 导出后切换 |
|
||||
| P0 | 操作失败 | douyin_01 | 步骤 1 [goto_home] 失败: 视频加载超时 | 需要进一步调查 |
|
||||
| P1 | 操作失败 | douyin_01 | 步骤 3 [like] 失败: DouyinOps.like() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
| P1 | 操作失败 | douyin_01 | 步骤 6 [collect] 失败: DouyinOps.collect() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
| P1 | 操作失败 | douyin_01 | 步骤 9 [like] 失败: DouyinOps.like() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
| P1 | 登录 | douyin_01 | douyin_01 未登录,部分互动操作可能受限 | 手动登录该账号,或使用 --export-cookies 导出后切换 |
|
||||
| P0 | 操作失败 | douyin_01 | 步骤 2 [search] 失败: SEARCH_KEYWORD 未替换,搜索无效 | 需要进一步调查 |
|
||||
| P1 | 操作失败 | douyin_01 | 步骤 3 [click_search_result] 失败: 不在搜索结果页 | 需要进一步调查 |
|
||||
| P1 | 操作失败 | douyin_01 | 步骤 5 [like] 失败: DouyinOps.like() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
| P1 | 登录 | douyin_02 | douyin_02 未登录,部分互动操作可能受限 | 手动登录该账号,或使用 --export-cookies 导出后切换 |
|
||||
| P1 | 操作失败 | douyin_02 | 步骤 3 [like] 失败: DouyinOps.like() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
| P1 | 操作失败 | douyin_02 | 步骤 6 [collect] 失败: DouyinOps.collect() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
| P1 | 操作失败 | douyin_02 | 步骤 9 [like] 失败: DouyinOps.like() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
| P1 | 登录 | douyin_02 | douyin_02 未登录,部分互动操作可能受限 | 手动登录该账号,或使用 --export-cookies 导出后切换 |
|
||||
| P1 | 操作失败 | douyin_02 | 步骤 5 [like] 失败: DouyinOps.like() got an unexpected keyword argument 'probability' | 需要进一步调查 |
|
||||
|
||||
## 系统级检查
|
||||
|
||||
| 检查项 | 状态 | 说明 |
|
||||
|--------|------|------|
|
||||
| Chrome 版本 | ✅ | Google Chrome 147.0.7727.138 |
|
||||
| Patchright | ❌ | 未安装 |
|
||||
| 数据库 | ✅ | /Users/chengzige/workbuddy-agent-os/agent-local/tools/matrix/data/matrix.db |
|
||||
| 蓝图 douyin_browse_v2 | ✅ | /Users/chengzige/workbuddy-agent-os/agent-sync/05_tools/07_matrix/blueprints/douyin_browse_v2.json |
|
||||
| 蓝图 douyin_search_browse | ✅ | /Users/chengzige/workbuddy-agent-os/agent-sync/05_tools/07_matrix/blueprints/douyin_search_browse.json |
|
||||
Reference in New Issue
Block a user