Files
MediaCrawler/mac-agent-os-main/03_knowledge/99_system/matrix/matrix-known-pitfalls.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

162 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Matrix 养号系统已知坑与解决方案
tags: [matrix, pitfalls, troubleshooting, camoufox, chrome, macos]
created: 2026-05-29
updated: 2026-05-29
nature: method
collected: true
collected_date: 2026-06-09
---
## 浏览器引擎
### Camoufox Profile 锁冲突
**现象**:`TargetClosedError`、页面无法操作、养号快速失败
**根因**:两个浏览器实例争用同一 profile 目录,`.parentlock` 锁文件被占用
**场景**:
- 抖音 daemon 模式浏览器保持运行,小红书复用同 identity_dir 启动新实例
- 上次进程异常退出,锁文件未清理
**解决**:
```bash
# 清理残留锁文件
find identities/ -name ".parentlock" -delete
```
**预防**:Phase 间使用 `--no-daemon` 确保浏览器正常关闭(`conn.close()`)
### Camoufox 启动失败
**现象**:浏览器进程无法启动或立即退出
**排查**:
1. 检查 `.user_data/` 目录锁文件(`.parentlock`)
2. 检查 config.yaml 语法
3. 检查 Camoufox 二进制是否可用
### Chrome 148+ Emulation API 失效
**现象**:`Emulation.setDeviceMetricsOverride` 报错或无效果
**根因**:Chrome 148 移除了该 CDP 命令
**解决**:改用 `set_viewport_size` 方法
## macOS 系统
### 窗口激活限制
**现象**:点击操作不响应,元素未被触发
**根因**:macOS 限制后台进程操控前台窗口
**解决**:AppleScript 激活窗口 + 双击策略
```applescript
tell application "System Events" to set frontmost of process "Firefox" to true
```
### macOS 26.4 .so 签名问题
**现象**:`ModuleNotFoundError` 或 `OSError: dlopen` 加载 .so 失败
**根因**:系统升级后 Team ID 不匹配
**解决**:ad-hoc 签名
```bash
codesign --force --sign - /path/to/file.so
# 批量签名
find /path/to/venv -name "*.so" -exec codesign --force --sign - {} \;
```
### Python stdout 缓冲
**现象**:后台运行日志文件为空或延迟写入
**根因**:Python 后台进程 stdout 默认全缓冲(非终端环境)
**解决**:
```bash
PYTHONUNBUFFERED=1 nohup python3 script.py > log.txt 2>&1 &
```
或检查账号级日志文件而非 phase 级日志。
## XHS 特有
### QR 检测墙卡死
**现象**:弹出大弹窗后无响应,养号停滞
**根因**:XHS 非常用登录检测,弹窗无自动超时
**解决**:JS 检测 QR 墙关键词 → 定位"返回首页"按钮 → L 型鼠标路径点击
**区分**:QR 墙 ≠ 未登录。QR 墙是频控触发,多刷会恢复。
### 黑屏
**现象**:瀑布流页面变黑,卡片不可见
**根因**:SPA 状态异常
**解决**:点击底部导航"发现" tab 刷新页面状态
### AI-layout 布局差异
**现象**:搜索栏消失、首卡位置偏移
**根因**:指纹分辨率 + DPR 触发 A/B 测试
**解决**:
1. 调整指纹(screen ≥ 1920x1080, DPR ≥ 1.25)
2. 代码兼容(三重搜索降级、通用 href 匹配)
### 登录检测误判
**现象**:已登录但被判定为未登录
**根因**:先关闭弹窗再检测 → 弹窗已隐藏 → 无法检测登录提示
**解决**:先检测登录状态 → 再 dismiss_login_modal
## 抖音特有
### Draft.js 输入不可靠
**现象**:评论内容无法输入或粘贴后消失
**根因**:Draft.js 只认系统级键盘事件
**解决**:pbcopy + Meta+V,不用 page.fill/type/keyboard.type
### 视频页评论区输入框在视口外
**现象**:评论发送失败,输入框不可交互
**根因**:输入框 y ~2212px,不在可视区域
**解决**:scrollIntoView → 等待 DraftEditor 懒加载 → click 容器触发激活
## 代码层面
### identity_dir 路径构造
**坑**:仅用 identity_name 拼接路径可能错误(如 `douyin_01_camo` ≠ `douyin_01`)
**正确做法**:从 accounts.yaml 读取 identity_dir 字段
### 窗口位置读取
**坑**:config.yaml 中无窗口位置字段
**正确做法**:从 accounts.yaml 读取,运行结束不回写
### argparse daemon 参数
**坑**:`store_true` + `getattr(args, 'daemon', True)` 当参数为 None 时返回 None 而非 True
**正确做法**:`BooleanOptionalAction` + `args.daemon if args.daemon is not None else True`
### page.evaluate() 无限挂起
**现象**:养号运行到某一步突然停止,无错误日志,浏览器进程存活
**根因**:Playwright 的 `page.evaluate()` 在页面状态异常时无限挂起,**无默认超时**
**解决**:所有 `page.evaluate()` 调用加 `asyncio.wait_for()` 超时(8-10s)
**影响范围**:所有涉及 JS 调用的函数(dismiss_login_modal, get_note_cards, click_refresh_button 等)
**注意**:超时会捕获 `asyncio.TimeoutError`,返回 False/None,不会导致进程退出
### 搜索结果页无 FAB 刷新按钮
**现象**:搜索返回首页后 click_refresh_button() 一直在找按钮,日志显示"刷新瀑布流页面..."长时间无进展
**根因**:go_back_to_home() 后可能回到搜索页,搜索页没有右下角 FAB 刷新按钮
**解决**:click_refresh_button() 加 10s 超时 → 找不到按钮安全返回 False → 流程继续
## 诊断方法论
遇到异常时按以下流程处理:
1. **环境因素**:浏览器版本变化?网络波动?进程锁残留?文件被占用?
2. **人为操作**:用户手动关闭浏览器?拖拽窗口?修改配置?
3. **确认代码问题**:记录日志,确认后再改
4. **读文档**:查看项目规划/架构设计,不偏离已有设计
5. **一次改一处**:改完验证再继续
**反面教材**:Chrome 148 升级导致 CDP API 失效,反复修改 cdp_connector.py 6 次把好的改坏了。