Files
MediaCrawler/mac-agent-os-main/05_tools/07_matrix/docs/IDENTITY_FACTORY.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

13 KiB
Raw Blame History

🦀 身份工厂:反检测 + 持久化标准化方案

基于 Camoufox 的「反检测伪装」+「持久化上下文」构建的多账号身份管理系统 版本: v1.0 | 日期: 2026-05-03


一、核心认知纠偏

1.1 反检测 ≠ 反持久化

概念 定义 关系
反检测 (Anti-Detection) 让网站无法识别你是自动化工具/不同身份 Camoufox 的设计目标
反持久化 (Anti-Persistence) 每次关闭后清空所有状态 Camoufox 的默认行为(不是设计目标)
持久化 (Persistence) 保存并复用登录态、浏览数据 Camoufox 完全支持,只是需要正确配置

关键结论:Camoufox 的默认行为(临时 profile + 随机指纹)是为了开发测试方便,不代表它不支持持久化。其 Playwright API 天然支持 launch_persistent_context + user_data_dir。

1.2 Camoufox 的真正优势

维度 Chrome Profiles Camoufox 持久化
指纹隔离 ❌ 同一台机器的真实指纹 ✅ 每身份独立伪造指纹
反检测深度 ❌ JS 层修补(易被检测) ✅ C++ 源码级修改(底层注入噪声)
内核优势 ❌ Chrome 被重点监控 ✅ Firefox 冷门,避开重点关照
Cloudflare 通过率 ~50% 88.58%(2026 评测)
身份隔离 ❌ 数据隔离 ≠ 身份隔离 ✅ 真正的"不同人用不同电脑"
持久化能力 ✅ user-data-dir 原生支持 ✅ persistent_context + user_data_dir

1.3 当前代码的三个致命缺陷

缺陷一:没有使用持久化上下文

位置:cdp_connector.py:69-104 — _launch_camoufox()

cf = AsyncCamoufox(**kwargs)
self._camoufox_browser = await cf.start()

start() → AsyncNewBrowser(..., persistent_context=False) → playwright.firefox.launch()(临时 profile)

影响:每次启动生成 /tmp/playwright_xxx/ 临时目录,所有登录态丢失。

缺陷二:没有固化指纹

位置:cdp_connector.py:73-85

kwargs = {
    'os': 'windows',      # 只约束了范围(Windows 池)
    'humanize': 1.5,
    # ← 没有 fingerprint 参数
}

链路:launch_options() → if fingerprint is None → generate_fingerprint(random) → 每次指纹不同

影响:抖音服务端检测到「同一 session_id 对应不同设备指纹」→ 强制短信验证。

缺陷三:Cookie 注入是错误做法

位置:yanghao_runner.py:149-164

cookie_file = ... / f"{acct_id}_cookies.json"
cookies = json.loads(cookie_file.read_text())
# 注入 Cookie
for c in cookies:
    await conn.context.add_cookies([{...}])

问题:抖音风控的校验逻辑是「session_id + 设备指纹」双重校验。Cookie 注入只传了 session_id,但当前设备的随机指纹与当初登录时的指纹不匹配 → 风控拦截 → 强制短信验证。


二、正确架构:身份工厂(Identity Factory)

2.1 核心理念

把「反检测伪装」和「持久化登录」变成标准化工程组件:

┌──────────────────────────────────────────────────────────┐
│                    身份工厂 (Identity Factory)             │
├───────────────┬────────────────┬─────────────────────────┤
│  create_identity  │  login_identity   │     run_task            │
│  (BrowserForge    │  (手动登录一次     │     (以登录态自动执行)    │
│   生成固化指纹)   │    state 保存)    │                         │
├───────────────┴────────────────┴─────────────────────────┤
│                    identities/                            │
│   ├── douyin_01/        ← 第一个身份                      │
│   │   ├── config.yaml   ← 固化指纹 + 代理配置             │
│   │   └── user_data/    ← Firefox 持久化 Profile          │
│   ├── douyin_02/        ← 第二个身份                      │
│   │   ├── config.yaml                                    │
│   │   └── user_data/                                     │
│   └── ...                                                │
└──────────────────────────────────────────────────────────┘

2.2 核心规则:一手机号 = 一身份

同手机号的抖音和小红书账号必须共用同一个 identity_dir。

这是经过实践验证的结论:

❌ 错误做法 ✅ 正确做法
douyin_01 → identities/douyin_01_camo douyin_01 → identities/douyin_01_camo
xhs_01 → identities/xhs_01(新建身份) xhs_01 → identities/douyin_01_camo(复用)
结果:两个浏览器指纹,两个登录态 结果:一个浏览器指纹,一份登录态,抖音和小红书 cookie 共存

为什么必须相同?

  • 一个手机号绑定一个实际的"人",反检测的本质是让平台认为你是"同一个人在不同网站活动"
  • 抖音和小红书分别存储 session cookie,互不冲突
  • 只需用 CookieGuard 保护对方平台的 cookie(删除时别误删)

代码中如何配置(accounts.override.yaml):

- id: douyin_04
  phone: '18550099083'
  enabled: true
- id: xhs_04
  phone: '18550099083'   # 同手机号
  enabled: true

MatrixManager 的 list_accounts() 方法会自动为同手机号的 xhs 账号分配与 douyin 相同的 identity_dir。

验证方法:

cd scripts && python -c "
from mc.engine import resolve_account
a = resolve_account('xhs_04')
print(a.get('identity_hint'))  # 输出: douyin_04(与 douyin_04 相同)
"

2.2 目录结构

agent-local/tools/matrix/
├── identities/                  # 所有身份集中存放
│   ├── douyin_01/               # 抖音主号
│   │   ├── config.yaml          # 指纹 + 代理配置(可版本控制)
│   │   └── user_data/           # 持久化 Profile(不提交 Git)
│   ├── douyin_02/               # 抖音副号
│   │   ├── config.yaml
│   │   └── user_data/
│   └── douyin_camo01/           # 第三个号(Chrome 或 Camoufox)
│       ├── config.yaml
│       └── user_data/
├── scripts/                     # 已有脚本,需改造
│   ├── cdp_connector.py         # → 新增: launch_camoufox_persistent()
│   ├── yanghao_runner.py        # → 新增: --identity 模式
│   ├── camoufox_manager.py      # → 改造: 支持 persistent_context
│   └── ... (新建)
│   ├── create_identity.py       # 生成新身份(指纹固化)
│   ├── login_identity.py        # 首次手动登录
│   └── run_task.py              # 以已登录身份执行任务
└── config/
    └── accounts.yaml            # → 重构: 指向 identities/ 目录

2.3 配置文件格式 config.yaml

# identities/douyin_01/config.yaml
identity:
  name: "douyin_01"
  platform: "douyin"
  proxy: null                    # 可选:固定代理
  notes: "抖音主号"

# 由 BrowserForge 生成并固化的指纹
fingerprint:
  navigator:
    userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0"
    platform: "Win32"
    hardwareConcurrency: 8
    deviceMemory: 8
    language: "zh-CN"
  screen:
    width: 1920
    height: 1080
    availWidth: 1920
    availHeight: 1040
    colorDepth: 24
  webgl:
    vendor: "Google Inc. (Intel)"
    renderer: "ANGLE (Intel, Intel(R) UHD Graphics (0x00009BC4) Direct3D11 vs_5_0 ps_5_0)"
  # ... 完整指纹由 BrowserForge 生成

2.4 关键 API:持久化上下文

AsyncCamoufox(persistent_context=True, user_data_dir=path, fingerprint=fixed_fp)
    ↓
AsyncNewBrowser(..., persistent_context=True)
    ↓
playwright.firefox.launch_persistent_context(user_data_dir=path, ...)
    ✅ 所有状态保存到 path 下
    ✅ 下次启动直接复用

对应 Chrome 的方案:

Google Chrome --user-data-dir=path --remote-debugging-port=port
    ↓
CDP connect
    ✅ 所有状态保存在 path 下
    ✅ 浏览器不退出,状态持久

两者本质相同,差异在于:

  • Chrome:浏览器进程常驻 + CDP 连接
  • Camoufox:launch_persistent_context 管理生命周期

三、标准化流程

3.1 创建身份 → create_identity

BrowserForge.generate()
    ↓
生成完整设备指纹(固定)
    ↓
写入 identities/{name}/config.yaml
    ↓
✅ 身份创建完成

3.2 首次登录 → login_identity

启动 Camoufox(headless=False, persistent_context=True, user_data_dir=path, fingerprint=fixed)
    ↓
打开目标网站(抖音首页)
    ↓
弹窗等待 → 用户手动登录
    ↓
用户按 Enter 确认
    ↓
所有登录态保存到 user_data/
    ↓
✅ 身份激活完成

这是唯一一次手动操作。之后所有任务复用这个 state。

3.3 日常任务 → run_task

启动 Camoufox(headless=True, persistent_context=True, user_data_dir=path, fingerprint=fixed)
    ↓
直接以已登录状态访问抖音
    ↓
执行蓝图操作(浏览/点赞/收藏等)
    ↓
保持浏览器不退出,继续下一轮
    ↓
✅ 循环执行

3.4 多账号并行

for identity in [douyin_01, douyin_02, douyin_camo01]:
    创建身份目录
    首次登录(手动)
    
# 日常运行
asyncio.gather(
    run_loop("douyin_01"),
    run_loop("douyin_02"),
    run_loop("douyin_camo01"),
)

四、与现有代码的关系

4.1 保留的部分

文件 用途 保留
blueprints/ 蓝图定义 ✅ 不变
douyin_ops.py 原子操作 ✅ 不变
atom_ops.py 原子操作 ✅ 不变
auth_manager.py 登录状态检测 ✅ 改进
task_engine.py 蓝图执行引擎 ✅ 改进加载方式
anti_detection.py 反检测 ✅ 改进
accounts.yaml 账号配置 🛠 重构格式

4.2 需要改造的文件

文件 改造内容 优先级
cdp_connector.py 新增 _launch_camoufox_persistent(),支持 persistent_context + user_data_dir + 固化指纹 P0
yanghao_runner.py 新增 --identity 模式,通过身份目录启动 P0
camoufox_manager.py 改造 --launch 使用持久化上下文 P1
accounts.yaml 新增 identity_dir 字段指向 identities/ P1
config_template/ 更新模板 P2

4.3 新增文件

文件 功能 优先级
scripts/create_identity.py 用 BrowserForge 生成指纹并创建身份目录 P0
scripts/login_identity.py 标准化首次登录流程 P0
scripts/run_task.py 以已登录身份执行自动化任务 P1
docs/IDENTITY_FACTORY.md 本文档 ✅ 已完成

五、关键注意事项

5.1 user_data 不可共享

  • 每个身份独立的 user_data/ 目录
  • 禁止混用,否则身份关联
  • 禁止提交到 Git(包含登录态)

5.2 指纹固化后不可变

  • 一旦身份创建完成,config.yaml 中的指纹不可修改
  • 修改指纹 = 换了一台电脑 → 掉登录
  • 如果需要新指纹 → 创建新身份,重新登录

5.3 代理一致性

  • 一个身份最好绑定固定代理
  • 代理变更会触发 IP 地理位置突变 → 风控
  • 在 config.yaml 的 identity.proxy 中指定

5.4 浏览器常驻模式

  • 登录后浏览器不退出(当前循环模式正确)
  • persistent_context 确保状态即时刷新
  • 避免频繁启停(减少指纹比对次数)

5.5 检测结论

根据 2026 反检测浏览器评测,Camoufox 在以下维度表现:

指标 Camoufox Chrome stealth Chrome 原生
Cloudflare 通过率 88.58% 11.21% (patchright) ~50%
Canvas 指纹伪装 ✅ C++ 级 ⚠️ JS 级 ❌
WebGL 伪装 ✅ ⚠️ ❌
字体伪装 ✅ ⚠️ ❌
多身份隔离 ✅ 身份级 ⚠️ Profile 级 Profile 级

Camoufox + 持久化上下文 + BrowserForge 固化指纹 + 固定代理 = 当前最优方案。