Files
MediaCrawler/mac-agent-os-main/archive_docs/matrix_docs/IMPLEMENTATION_GUIDE.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

29 KiB
Raw Blame History

全自动矩阵养号运维系统 - 完整落地实施手册

版本:v2.0
适用平台:抖音、小红书、快手、知乎
运行环境:macOS (Apple Silicon), Colima, Docker
最后更新:2026-04-27


目录

  1. 项目概述与目标
  2. 第一部分:隐身登录系统
  3. 第二部分:智能养号自动化系统
  4. 第三部分:系统完整工作流
  5. 第四部分:落地实施具体步骤
  6. 第五部分:关键技术栈
  7. 第六部分:成本估算
  8. 附录:常见问题与踩坑记录

一、项目概述与目标

1.1 项目定义

在 Mac (Apple Silicon) 上构建一套覆盖抖音、小红书、快手、知乎的全自动矩阵养号系统。实现从安全登录、拟人化浏览、智能互动到回复评论的全链路自动化。

1.2 核心设计原则

  • 高隐蔽性:从浏览器指纹、网络出口、行为特征三个维度做到不被平台风控识别
  • 低成本启动:核心依赖开源工具,初期月成本控制在 ¥135-600
  • 自我进化:采用"人工示教 → AI学习 → 自动回放"模式,适应平台UI变化
  • 人机协同:登录/验证码环节人工介入,重复性操作用自动化完成

1.3 前置条件

  • 一台专用 Mac (Apple Silicon),仅用于养号
  • 浏览器前台运行,不使用无头模式 (headless: false)
  • 登录、验证码环节人工配合
  • 5-6 个初始账号,使用 2-3 套反检测框架轮换
  • 每个账号绑定独立静态住宅IP

二、第一部分:隐身登录系统

2.1 架构总览

🧠 AI 总调度器 (OpenClaw / Python asyncio)
    │
    ├── Docker 容器 1: Camoufox (Firefox) → 账号A → 独立IP_1
    ├── Docker 容器 2: Camoufox (Firefox) → 账号B → 独立IP_2
    ├── Docker 容器 3: Patchright (Chromium) → 账号C → 独立IP_3
    ├── Docker 容器 4: Patchright (Chromium) → 账号D → 独立IP_4
    └── Docker 容器 5: Camoufox (Firefox) → 账号E → 独立IP_5

轮换策略:

  • 3个账号使用 Camoufox (Firefox内核)
  • 2个账号使用 Patchright (Chromium内核)
  • 避免所有账号使用同一框架,降低群体特征关联风险

2.2 容器运行时选型:Colima

为什么用 Colima 而不是 Docker Desktop:

  • Colima 是 macOS 上最轻量的容器运行时,基于 Lima
  • 默认行为更接近原生 Linux 环境,不挂载 /.dockerenv 标志文件
  • 资源占用小,适合长时间运行
  • 开源免费,无 Docker Desktop 的商用限制

安装命令:

brew install colima docker docker-compose
colima start --cpu 4 --memory 8 --disk 50

验证安装:

docker ps
# 应显示空的容器列表,无报错

2.3 Docker 环境反检测技术清单

以下每一项都是经过验证的对抗手段,必须全部配置,缺一不可。

序号 平台检测手段 具体表现 风险等级 我们的对抗方法 具体实现
1 /.dockerenv 文件 检查根目录是否存在该标志文件 ⚠️ 高 删除该文件 Dockerfile: RUN rm -f /.dockerenv
2 /proc/1/cgroup 关键词 检查cgroup是否包含 "docker" 字符串 ⚠️ 高 挂载伪造的cgroup文件 -v /host/proc/1/cgroup:/proc/1/cgroup:ro
3 环境变量 container=docker 检测环境变量中是否包含docker标识 ⚠️ 中 清除环境变量 Dockerfile: ENV container=""
4 /etc/machine-id 系统唯一标识,虚拟机/Docker有固定值 ⚠️ 中 挂载宿主机真实文件 -v /etc/machine-id:/etc/machine-id:ro
5 D-Bus 服务缺失 真实桌面系统必有的进程间通信服务 ⚠️ 中 安装并启动dbus RUN apt-get install -y dbus
6 显卡/WebGL 指纹 检查是否含 "llvmpipe" 等软件渲染标识 ⚠️ 高 Camoufox自动伪造真实GPU信息 由Camoufox在编译层处理
7 MAC地址虚拟化 Docker默认生成 02:42:xx:xx:xx:xx 段虚拟MAC ⚠️ 中 挂载宿主机网卡或指定固定MAC --mac-address 00:1B:63:84:45:E6
8 CPU信息 /proc/cpuinfo 显示虚拟化标识 ⚠️ 低 不做特殊处理,Colima默认较干净 -
9 内存/磁盘大小 异常小的内存或磁盘容量 ⚠️ 低 分配合理资源(8G内存,50G磁盘) colima配置参数

Dockerfile 完整模板:

# Camoufox 基础镜像
FROM ubuntu:22.04

# 清除Docker标志文件
RUN rm -f /.dockerenv

# 清除环境变量
ENV container=""

# 安装桌面依赖
RUN apt-get update && apt-get install -y \
    dbus \
    libgtk-3-0 \
    libnotify4 \
    libnss3 \
    libxss1 \
    libxtst6 \
    xdg-utils \
    libatspi2.0-0 \
    libdrm2 \
    libgbm1 \
    libxcb1 \
    libxkbcommon0 \
    libasound2 \
    && rm -rf /var/lib/apt/lists/*

# 启动dbus服务
RUN mkdir -p /var/run/dbus && dbus-daemon --system

# 创建非root用户(真实用户不会用root跑浏览器)
RUN useradd -m -s /bin/bash browser
USER browser
WORKDIR /home/browser

# 安装Camoufox(具体步骤见Camoufox官方文档)
# ...

docker-compose.yml 完整模板:

version: '3.8'

services:
  account_01:
    build:
      context: ./docker/camoufox
      dockerfile: Dockerfile
    container_name: matrix_account_01
    volumes:
      - ./profiles/account_01:/home/browser/.mozilla  # Cookie持久化
      - ./scripts:/home/browser/scripts
      - /etc/machine-id:/etc/machine-id:ro              # 宿主机machine-id
    environment:
      - PROXY_SERVER=socks5://your-proxy-ip-1:1080       # 独立代理IP
      - PROXY_USER=your_username
      - PROXY_PASS=your_password
      - DISPLAY=:99
    mac_address: 00:1B:63:84:45:E1                       # 固定MAC
    ports:
      - "9221:9222"  # CDP调试端口,每个容器映射到宿主机不同端口
    shm_size: '2gb'
    restart: unless-stopped

  account_02:
    image: patchright-browser:latest
    container_name: matrix_account_02
    volumes:
      - ./profiles/account_02:/home/browser/.config/chromium
      - ./scripts:/home/browser/scripts
      - /etc/machine-id:/etc/machine-id:ro
    environment:
      - PROXY_SERVER=socks5://your-proxy-ip-2:1080
      - DISPLAY=:99
    mac_address: 00:1B:63:84:45:E2
    ports:
      - "9222:9222"
    shm_size: '2gb'
    restart: unless-stopped

  # account_03, account_04, account_05 类推

2.4 浏览器层反检测框架详解

2.4.1 Camoufox (Firefox内核)

为什么选择Camoufox:

  • 在编译阶段修改Firefox源码,不是运行时打补丁
  • 从根源消除 navigator.webdriver 等自动化特征
  • WebGL/Canvas/字体指纹均做真实化随机处理
  • 对国际主流平台(TikTok, Instagram等)兼容性好

Camoufox 编译级修改点:

修改点 解决的问题 技术细节
navigator.webdriver 强制返回 false 在Navigator接口实现层硬编码,JS无法检测
CDP Runtime 泄漏 移除调试管道痕迹 删除 --remote-debugging-pipe 参数
WebGL 指纹 伪造真实GPU型号 注入Apple M系列GPU指纹
Canvas 指纹 每次渲染添加微噪声 噪声可配置,默认人类无法察觉
字体指纹 模拟真实系统字体列表 内置macOS/Windows字体清单
时区一致性 IP代理对应时区自动同步 启动时检测IP Geo位置自动设置

使用示例:

from camoufox import AsyncCamoufox

async with AsyncCamoufox(
    headless=False,
    proxy="socks5://ip:port",
    user_data_dir="./profiles/acc01",
    screen={"width": 390, "height": 844},
    geo={"timezone": "Asia/Shanghai"}
) as browser:
    page = await browser.new_page()
    await page.goto("https://www.douyin.com")

2.4.2 Patchright (Chromium内核)

为什么需要Patchright:

  • 基于Chromium内核,对国内Webkit平台(抖音/小红书)兼容性更好
  • 修补CDP协议和JS运行时泄漏
  • 与Playwright API兼容,学习成本低

与Camoufox配合使用:

  • 账号A、B、E → Camoufox (Firefox)
  • 账号C、D → Patchright (Chromium)
  • 关键:不要让所有账号使用同一浏览器内核

2.4.3 CDP协议连接方式

import asyncio
from patchright.async_api import async_playwright

async def connect_to_browser(cdp_port: int):
    async with async_playwright() as p:
        browser = await p.chromium.connect_over_cdp(
            f"http://localhost:{cdp_port}"
        )
        context = browser.contexts[0]
        page = context.pages[0] if context.pages else await context.new_page()
        return page

2.5 移动端伪装与强制跳转拦截

2.5.1 三层对抗策略

第一层:伪装成"无App环境的普通移动浏览器"
参数 设置值 目的
User-Agent Mozilla/5.0 (Linux; Android 10; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36 伪装成Android手机Chrome
UA关键注意 绝对不能包含 MicroMessenger、douyin、xiaohongshu、kuaishou 等App标识 避免被识别为App内嵌浏览器
navigator.standalone 通过CDP注入强制返回 false 告诉页面"没有安装PWA"
navigator.platform Linux armv8l 与UA保持一致性

注意:UA中的 Android 字样不能省略,部分平台对 iPhone UA的跳转更激进。

第二层:CDP拦截URL Scheme跳转(最关键防线)
async def setup_app_jump_interception(cdp_session):
    """拦截所有主流平台的App跳转协议"""
    blocked_schemes = [
        "xhdsdiscover://*",      # 小红书
        "snssdk1128://*",        # 抖音
        "snssdk1233://*",        # TikTok
        "kuaishou://*",          # 快手
        "zhihu://*",             # 知乎
        "weixin://*",            # 微信
        "alipays://*",           # 支付宝
        "taobao://*",            # 淘宝
        "openapp.jdmobile://*",  # 京东
        "intent://*",            # Android Intent
    ]
    
    await cdp_session.send("Fetch.enable", {
        "patterns": [
            {"urlPattern": scheme, "requestStage": "Request"}
            for scheme in blocked_schemes
        ]
    })
    
    def handle_interception(event):
        asyncio.ensure_future(
            cdp_session.send("Fetch.failRequest", {
                "requestId": event["requestId"],
                "errorReason": "Aborted"
            })
        )
    
    cdp_session.on("Fetch.requestPaused", handle_interception)
    return cdp_session
第三层:DOM弹窗清理(兜底方案)
REMOVE_OVERLAY_SCRIPT = """
() => {
    const overlay_selectors = [
        '[class*="download"]', '[class*="open-app"]', '[class*="app-guide"]',
        '[class*="launch-app"]', '[class*="open-in-app"]',
        '.open-in-app', '.app-launch-mask', '.download-tip', '.bottom-bar',
        '.download-banner', '.open-app-btn', '.app-download-tip',
        '.open-app-layer', '.download-guide-mask',
        '.open-in-app-bar', '.app-open-button',
        '#app-launch-dialog', '#open-app-modal', '#download-modal',
    ];
    
    let removed_count = 0;
    overlay_selectors.forEach(selector => {
        document.querySelectorAll(selector).forEach(el => {
            el.remove();
            removed_count++;
        });
    });
    
    document.body.style.overflow = '';
    document.body.style.position = '';
    document.body.style.overflowY = 'auto';
    
    return removed_count;
}
"""

2.5.2 移动端视口配置

MOBILE_VIEWPORT_CONFIG = {
    "width": 390,
    "height": 844,
    "deviceScaleFactor": 3,
    "isMobile": True,
    "hasTouch": True,
    "screenOrientation": "portrait"
}

async def apply_mobile_viewport(cdp_session):
    await cdp_session.send("Emulation.setDeviceMetricsOverride", {
        "width": 390,
        "height": 844,
        "deviceScaleFactor": 3,
        "mobile": True,
        "screenOrientation": {"type": "portrait", "angle": 0}
    })
    await cdp_session.send("Emulation.setTouchEmulationOverride", {
        "enabled": True,
        "maxTouchPoints": 5
    })

2.6 IP代理配置

代理类型 月成本/个 稳定度 适用场景
静态住宅IP (推荐) ¥25-110 ⭐⭐⭐⭐ 长期养号,被识别风险最低
动态住宅IP ¥15-50 ⭐⭐⭐ 批量操作,但IP变化可能触发验证
数据中心代理 ¥5-20 ⭐⭐ 初期测试,但易被风控识别

2.7 人工登录与Cookie持久化

步骤1:启动容器 + 应用代理
步骤2:浏览器弹出(前台,390x844手机比例)
步骤3:人工输入账号密码 + 验证码 + 勾选"记住我"
步骤4:确认登录成功 → Cookie自动写入挂载卷
步骤5:关闭浏览器 → Cookie持久化保留
步骤6:重启容器,验证持久化是否正常
async def check_login_status(page, platform: str):
    """检查账号是否仍处于登录状态"""
    login_indicators = {
        "douyin": "document.querySelector('[data-e2e=\"user-avatar\"]') !== null",
        "xiaohongshu": "document.querySelector('.user-avatar') !== null",
        "kuaishou": "document.querySelector('.user-avatar') !== null",
        "zhihu": "document.querySelector('.AppHeader-profile') !== null",
    }
    js_code = login_indicators.get(platform)
    if not js_code:
        return False
    try:
        return await page.evaluate(js_code)
    except:
        return False

三、第二部分:智能养号自动化系统

3.1 核心设计:人工示教 → 任务蓝图 → AI回放

设计理念:

  • 不编写死板的点击坐标脚本
  • 人工操作一次,系统自动学习
  • 生成结构化"任务蓝图",AI据此回放
  • 平台UI变化时自我修复,失败时降级处理

3.2 原子操作定义

原子操作ID 操作名称 描述 完成确认
AO_NAV 页面导航 跳转到指定URL 目标页面关键元素出现
AO_CLICK 点击元素 点击指定按钮/链接 期望的页面变化发生
AO_INPUT 输入文本 在输入框输入内容 输入框内容与预期一致
AO_SCROLL 滑动/滚动 上下滑动页面 滚动位置发生变化
AO_SWIPE 触摸滑动 模拟手指滑动(视频切换) 内容切换到下一条
AO_WAIT 等待 停留浏览一段时间 等待时间达标
AO_SEARCH 搜索 搜索关键词 搜索结果加载
AO_LIKE 点赞 点亮爱心/拇指 按钮状态变为"已赞"
AO_COLLECT 收藏 收藏内容 按钮状态变为"已收藏"
AO_COMMENT 评论 发表评论 评论出现在评论区
AO_REPLY 回复评论 回复他人评论 回复内容发送成功
AO_FOLLOW 关注 关注用户 按钮变为"已关注"

3.3 养号任务清单

抖音任务

任务ID 任务名称 涉及原子操作 预估耗时
DY_001 浏览推荐页 AO_SWIPE, AO_WAIT 5-15分钟
DY_002 搜索并浏览 AO_SEARCH, AO_CLICK, AO_WAIT 3-8分钟
DY_003 点赞视频 AO_LIKE 30秒
DY_004 评论视频 AO_COMMENT, AO_INPUT 1-2分钟
DY_005 回复评论 AO_NAV, AO_CLICK, AO_REPLY 2分钟
DY_006 关注用户 AO_FOLLOW 30秒
DY_007 收藏视频 AO_COLLECT 30秒
DY_008 浏览同城 AO_NAV, AO_SWIPE, AO_WAIT 5分钟
DY_009 查看主页 AO_NAV, AO_SCROLL 2分钟

小红书任务

任务ID 任务名称 涉及原子操作 预估耗时
XHS_001 浏览首页推荐 AO_SCROLL, AO_CLICK, AO_WAIT 5-15分钟
XHS_002 搜索浏览 AO_SEARCH, AO_SCROLL, AO_CLICK 5分钟
XHS_003 点赞笔记 AO_LIKE 30秒
XHS_004 收藏笔记 AO_COLLECT 30秒
XHS_005 评论笔记 AO_COMMENT, AO_INPUT 1-2分钟
XHS_006 关注博主 AO_FOLLOW 30秒

快手任务

任务ID 任务名称 涉及原子操作
KS_001 刷推荐视频 AO_SWIPE, AO_WAIT
KS_002 点赞视频 AO_LIKE
KS_003 评论视频 AO_COMMENT, AO_INPUT

知乎任务

任务ID 任务名称 涉及原子操作
ZH_001 浏览推荐 AO_SCROLL, AO_CLICK, AO_WAIT
ZH_002 赞同回答 AO_LIKE
ZH_003 评论问题 AO_COMMENT, AO_INPUT
ZH_004 关注话题 AO_FOLLOW

3.4 任务蓝图完整数据结构

{
  "task_id": "DY_005",
  "task_name": "抖音_回复评论",
  "platform": "douyin",
  "version": "1.0.0",
  "created_at": "2026-04-27T10:00:00Z",
  "created_by": "human_demo",
  "description": "从抖音个人主页进入消息页,找到评论Tab,回复第一条未回复的评论",
  "estimated_duration_ms": 45000,
  
  "execution_environment": {
    "viewport": {"width": 390, "height": 844},
    "user_agent": "Mozilla/5.0 (Linux; Android 10; Pixel 5)...",
    "touch_enabled": true,
    "blocked_schemes": ["xhdsdiscover://*", "snssdk1128://*"],
    "overlay_removal": true
  },
  
  "steps": [
    {
      "step_id": 1,
      "step_name": "点击消息Tab进入通知页",
      "atomic_operation": "AO_CLICK",
      
      "locator": {
        "primary": "[data-e2e='message-tab']",
        "fallback_xpath": "//div[contains(@class,'tab')]//span[contains(text(),'消息')]",
        "fallback_visual": {
          "text": "消息",
          "description": "底部导航栏的消息图标按钮"
        }
      },
      
      "behavior": {
        "click_mode": "touch",
        "pre_delay_ms": [500, 1200],
        "touch_duration_ms": [50, 100],
        "post_delay_ms": [1500, 2500]
      },
      
      "post_checks": [
        {"type": "url_changed", "expected_pattern": "/notice/*"},
        {"type": "element_appeared", "selector": "[data-e2e='comment-tab']"}
      ],
      
      "on_failure": {"max_retries": 2, "fallback_action": "retry_with_visual"}
    }
  ],
  
  "completion_verification": {
    "success_indicators": [
      {"type": "element_appeared", "selector": "[data-e2e='reply-sent-success']"}
    ],
    "timeout_ms": 60000
  }
}

3.5 任务蓝图数据库设计

-- 任务蓝图主表
CREATE TABLE task_blueprints (
    id TEXT PRIMARY KEY,
    task_id TEXT NOT NULL,
    task_name TEXT NOT NULL,
    platform TEXT NOT NULL,
    version TEXT NOT NULL,
    status TEXT DEFAULT 'active',     -- 'active', 'deprecated', 'broken'
    browser_framework TEXT,
    viewport_config TEXT,
    entry_conditions TEXT,
    steps_json TEXT,
    completion_check_json TEXT,
    created_at TEXT DEFAULT (datetime('now')),
    updated_at TEXT DEFAULT (datetime('now')),
    deprecation_reason TEXT,
    replaced_by_version TEXT
);

-- 任务执行记录表
CREATE TABLE task_executions (
    id TEXT PRIMARY KEY,
    task_id TEXT NOT NULL,
    blueprint_version TEXT NOT NULL,
    account_id TEXT NOT NULL,
    browser_framework TEXT,
    container_id TEXT,
    proxy_ip TEXT,
    status TEXT,                      -- 'running', 'success', 'failed', 'timeout'
    started_at TEXT,
    completed_at TEXT,
    duration_ms INTEGER,
    error_message TEXT,
    screenshots TEXT,
    logs TEXT
);

-- 原子操作执行记录
CREATE TABLE operation_logs (
    id TEXT PRIMARY KEY,
    execution_id TEXT NOT NULL,
    step_id INTEGER,
    atomic_operation TEXT,
    pre_checks_passed BOOLEAN,
    execution_success BOOLEAN,
    post_checks_passed BOOLEAN,
    locator_used TEXT,
    duration_ms INTEGER,
    error_detail TEXT,
    screenshot_path TEXT,
    created_at TEXT DEFAULT (datetime('now'))
);

-- UI变更记录
CREATE TABLE ui_changes (
    id TEXT PRIMARY KEY,
    task_id TEXT,
    platform TEXT,
    detected_at TEXT,
    element_changed TEXT,
    old_selector TEXT,
    new_selector TEXT,
    affected_blueprint_versions TEXT,
    resolution TEXT,
    notes TEXT
);

3.6 三级元素定位策略

class SmartLocator:
    """
    智能元素定位器
    Level 1: 录制的CSS选择器(90%场景)
    Level 2: 备选XPath(8%场景)
    Level 3: 本地MLX视觉定位(2%场景,兜底)
    """
    async def locate_element(self, page, step: dict):
        # Level 1: 首选CSS选择器
        primary = step["locator"]["primary"]
        try:
            element = await page.wait_for_selector(primary, timeout=3000)
            if element:
                return {"level": 1, "element": element}
        except:
            pass
        
        # Level 2: 备选XPath
        fallback_xpath = step["locator"].get("fallback_xpath")
        if fallback_xpath:
            try:
                element = await page.wait_for_selector(f"xpath={fallback_xpath}", timeout=3000)
                if element:
                    return {"level": 2, "element": element}
            except:
                pass
        
        # Level 3: MLX视觉定位
        return await self._visual_locate(page, step)

3.7 本地MLX多模态后备

# 安装MLX和视觉模型
pip install mlx mlx-vlm

# 下载量化版视觉模型(Qwen2-VL-7B-4bit,内存占用<5GB)
python -c "
from mlx_vlm import load
model, processor = load('mlx-community/Qwen2-VL-7B-4bit')
"
async def mlx_vision_locate(image_bytes: bytes, target_description: str, target_text: str = ""):
    """使用本地MLX模型在截图中定位目标元素"""
    model, processor = get_mlx_model()
    image = Image.open(io.BytesIO(image_bytes))
    
    prompt = f"""在这张手机截图中,找到"{target_description}"的位置。
该元素的文字可能是"{target_text}"。
请返回该元素的外接矩形坐标,格式为:x1,y1,x2,y2
只返回坐标数字,不要包含其他内容。"""
    
    response = generate(model, processor, image=image, prompt=prompt, max_tokens=50)
    
    try:
        parts = response.strip().split(",")
        if len(parts) == 4:
            x1, y1, x2, y2 = map(int, parts)
            return {"x": (x1+x2)//2, "y": (y1+y2)//2, "x1":x1, "y1":y1, "x2":x2, "y2":y2}
    except:
        pass
    return None

MLX方案的优势:零网络延迟(200-500ms)、零API费用、数据不离本机。

3.8 养号行为拟人化参数

class BehaviorProfile:
    def __init__(self, account_id: str, persona: str = "normal"):
        self.params = {
            "action_delay": [200, 5000],       # 动作间隔(毫秒)
            "view_duration": [5000, 60000],    # 浏览停留(毫秒)
            "move_duration": [100, 800],       # 鼠标/触摸移动时间
            "typing_speed": [50, 200],         # 每字符毫秒
            "typo_probability": [0, 0.05],     # 打字错误概率
            "active_hours": [8, 23],           # 每日活跃时段
            "max_likes_per_hour": 20,
            "max_comments_per_hour": 5,
            "max_follows_per_hour": 10,
            "max_total_actions_per_day": 200,
        }

四、第三部分:系统完整工作流

4.1 日常运行全景

每日启动(定时/手动)
    │
调度器加载排班表,确定今日任务序列
    │
    ├── 启动容器1 + 加载代理
    ├── 启动容器2 + 加载代理
    └── 启动容器3 + 加载代理
    │
    检查Cookie登录状态
    有效 → 直接执行 | 过期 → 通知人工
    │
    各账号执行任务序列(浏览/点赞/评论/关注)
    │
    每个步骤:前置校验 → 执行 → 后置校验
    成功 → 记录日志 → 下一步
    失败 → 降级定位 → 重试 → 人工介入
    │
    冷却10-30分钟
    │
    释放容器,生成今日执行报告

4.2 账号熔断机制

class CircuitBreaker:
    def __init__(self, account_id: str):
        self.failure_count = 0
        self.max_failures = 3
        self.cooldown_minutes = 30
        self.is_open = False
    
    async def record_failure(self):
        self.failure_count += 1
        if self.failure_count >= self.max_failures:
            self.is_open = True
            await notify_admin(f"账号 {self.account_id} 连续失败已熔断")
    
    def can_execute(self) -> bool:
        if not self.is_open:
            return True
        if time.time() - self.opened_at > self.cooldown_minutes * 60:
            self.is_open = False
            self.failure_count = 0
            return True
        return False

五、第四部分:落地实施具体步骤

阶段0:环境准备(预计1-2天)

brew install colima docker docker-compose
colima start --cpu 4 --memory 8 --disk 50
docker ps  # 验证

pip install asyncio aiohttp playwright patchright camoufox
mkdir -p ~/matrix/{docker/{camoufox,patchright},profiles,scripts,data,logs,screenshots}

阶段1:隐身容器跑通 + 人工登录(预计2-3天)

  • 编写 Camoufox Dockerfile(含所有反检测配置)
  • 编写 Patchright Dockerfile
  • 编写 docker-compose.yml(5个容器)
  • 准备2个静态住宅IP
  • docker-compose up account_01 启动容器,人工登录抖音
  • 验证跳转拦截:小红书网页版是否有弹窗
  • 验证Cookie持久化

里程碑:2账号 × 2框架 × 独立IP,同时在线,无跳转弹窗。

阶段2:示教录制与蓝图生成(预计3-5天)

  • 编写CDP监听脚本
  • 连接容器,启动示教模式
  • 人工演示"抖音_浏览推荐页 + 点赞"完整流程
  • 验证生成的蓝图JSON结构是否合理
  • 录制3-5个基础任务蓝图,入库SQLite

阶段3:蓝图回放验证(预计3-5天)

  • 编写蓝图回放引擎
  • 验证自我修复:故意损坏选择器,观察降级定位
  • 连续3天存活率测试

里程碑:AI完成完整浏览+点赞+关注序列,无人工干预,3天内未被风控。

阶段4:集成调度器(预计2-3天)

  • asyncio调度器 + 排班表
  • 每日执行报告
  • crontab 定时启动

阶段5:扩展任务库与多平台(持续)

  • 小红书/快手/知乎核心蓝图录制
  • 接入 DeepSeek 评论生成
  • 5账号全量跑通,观察1周稳定性

阶段6:MLX本地视觉后备(预计1-2天)

  • 安装MLX + 下载 Qwen2-VL-7B-4bit
  • 集成视觉定位为第三级降级
  • 压测定位延迟(目标 < 500ms)

六、第五部分:关键技术栈总览

层级 工具 用途 是否免费
容器运行时 Colima 轻量Docker替代 ✅
反检测浏览器 Camoufox Firefox内核,编译级反检测 ✅
反检测浏览器 Patchright Chromium内核,修补CDP泄漏 ✅
CDP通信 nodriver / patchright 驱动浏览器 ✅
行为模拟 自定义触摸模拟 拟人化触摸操作 ✅
IP代理 静态住宅代理 独立IP出口 ❌
任务调度 Python asyncio 编排多账号并发 ✅
AI编排 OpenClaw (可选) 自然语言转任务指令 ✅
数据库 SQLite 存储蓝图和日志 ✅
多模态AI MLX + Qwen2-VL 本地视觉定位 ✅
评论生成 DeepSeek API 智能评论内容 ❌(极低)

七、第六部分:成本估算

初期5账号方案

项目 月成本 年成本 备注
静态住宅IP ×5 ¥125-550 ¥1500-6600 ¥25-110/个/月
反检测框架 ¥0 ¥0 开源
MLX本地模型 ¥0 ¥0 仅消耗电费
评论API ¥10-50 ¥120-600 DeepSeek按量付费
月总成本 ¥135-600

与商业方案对比

方案 月成本 (5账号) 灵活性 技术门槛
本方案 (开源自建) ¥135-600 ⭐⭐⭐⭐⭐ 中高
AdsPower + RPA ¥300-1000+ ⭐⭐⭐ 中
商业群控系统 ¥1000-5000 ⭐⭐ 低

八、附录:常见问题与踩坑记录

容器相关

Q: Docker ps 报错 "permission denied"

sudo usermod -aG docker $USER
# 重新登录终端

Q: 容器内浏览器无法启动,报错 "no display"

environment:
  - DISPLAY=host.docker.internal:0

反检测相关

Q: 平台仍然检测到WebDriver

  • 确认Camoufox使用最新版本
  • 确认没有传入 --enable-automation 参数
  • 通过CDP覆写 navigator.webdriver

Q: 小红书仍然强制跳转App

  • 检查UA中是否包含小红书App标识
  • 确认URL Scheme拦截是否生效
  • 尝试增加 navigator.standalone = false 覆写

蓝图相关

Q: 录制时选择器不稳定

  • 优先选择 data-e2e 等平台埋点属性
  • 避免依赖动态生成的class名
  • 使用相对位置关系作为备选定位

Q: MLX视觉定位速度慢

  • 确保使用4bit量化版模型
  • 降低截图分辨率(1920→960)
  • 先用OCR预筛选,再调用VL模型

此手册整合了完整讨论内容,后续开发过程中如有新问题,随时补充到附录。