潜在触达「路B」复刻教程

给同事 · 事无巨细 + 雷点 | 最后更新 2026-06-18 | 源文件 docs/runbooks/potential-touch-route-b-replicate.md
当前在跑的路B:无影云电脑一台机常驻「实时监控 + GUI 三连」——对你账号已 DM/RC 过、≥1 天没回的高/中意向 lead,一发新视频就自动点赞 + 评论1(评视频) + 评论2(搬DM)。老的派单二触 cron 已停,别再用。

0 · 先搞懂架构(不懂这个,排障全是瞎猜)

两个 Python 进程,同机各开一个窗口常驻:

进程干什么靠什么脆不脆
监控 watch
_realtime_touch_watch_wuying.py
调抖音网络接口盯关注流,逮 lead 新视频→写本地队列网络 API,不碰屏幕
消费 consume
_realtime_touch_consume_wuying.py
tail 队列→查话术表→调 GUI 执行器在抖音 PC 上点赞+评论鼠标键盘+屏幕+焦点

GUI 执行器 = douyin_comment_grounded.py,像真人一样移鼠标/打字/点按钮/截屏验证(点赞评论抖音没接口,只能扮真人)。它脆就脆在屏幕/焦点/坐标一变就出错。
回写:本地表模式下触达写本地 comment_log_YYYYMMDD.csv,需摆渡回 mac 跑 mark-second-touch.ts 入库(端点直连回写还没做,见雷点④+roadmap)。

路 A vs 路 B(caffeinate/雷点里都会提到,先认清):本教程讲的是 路 B = 监控 + 消费都在无影一台机常驻、同机闭环,真 7×24 不靠运营 Mac。路 A = 兜底备用,监控放 Mac 上跑(盯 lead 发新视频)、把名单摆渡给无影,无影只管发——万一无影上的监控不好使(cookie/网络)才退回它,这时 Mac 必须不睡(雷点⑯ caffeinate)。一句话:B = 全在无影;A = 监控在 Mac、摆渡给无影

0.5 · 潜在触达的人(sec_uid)哪来的 + 两个 id 别混(常被问)

sec_uid 不是单独「抓」的——评论采集就随评论入库了。每条评论入库时,评论者的 douyin_user_id(=sec_uid)一起写进 comments 表,全站 sec_uid 都来自这。潜在触达不另外抓 id,只是 second-touch-worklist.ts 从已有 sec_uid 里按规则筛名单(DM 过 + ≥N 天没回 + 高/中意向 + 未 stopped + next_eligible 到期)。

两个 id 别混(排障关键)

id是什么哪来的能搜人?
sec_uid
(douyin_user_id, MS4w…)
抖音内部稳定 id✅ 评论采集就有、一路带到队列❌ 搜索框打不进去
抖音号
(unique_id, 如 2091195012)
人看的账号号❌ comments 没存、要现场反查✅ 搜它最准·不撞名

enrich 接在消费端补这一步:消费拿到 sec_uid → resolve_number(sec) 现场反查出抖音号 → 填进搜索词按号精确核身(治撞名 + 未知客户无昵称,雷点⑧);反查失败回退昵称搜、不挡发。一条龙:

评论采集 → comments.sec_uid → worklist 筛名单 → special-follow.json(secUid列表)
→ 监控逮新视频(队列带 sec_uid) → 消费 enrich: sec_uid→抖音号 → 按号搜对人

1 · 前置 · 机器与账号

powercfg /change standby-timeout-ac 0
powercfg /change monitor-timeout-ac 0
powercfg /change disk-timeout-ac 0
powercfg /change hibernate-timeout-ac 0

关 Mac 休眠(仅当你在 Mac 上跑 route-B 相关长任务时) = 让 Mac 别睡,否则 route-A 兜底监控 / mac 侧 ferry / cron 一睡就停。这跟上面无影的 powercfg 是两台机、两套:Windows 用 powercfg,Mac 用 caffeinate,别搞混。

1.5 · 🔴 头号前置 · 关注覆盖(不做这个,监控逮不到任何人)

监控盯的是你账号的「关注流」——只有你账号关注了的人,他发新视频才会出现、才被逮到。 池子里的人如果你没关注,他发一百条你也逮不到。

2 · mac 端的料 · 你自己账号的池子(每人一套,不通用)

潜在触达对象 = 你自己账号 DM/RC 触达过、≥1 天没回、高/中意向的人。所以池子、话术表、关注 全是你账号下的、跟别人不通用——同事 A 的池子对同事 B 没用。

生成涉及 second-touch-worklist.ts(按你的 AKKE_ACCOUNT_ID 出名单)+ _gen-realtime-touch-table.py + 转换,目前由 fanny/PM 用你的账号跑、生成好给你摆渡。你拿到 3 份你账号专属文件:

文件内容
special-follow.json监控池(你账号 DM/RC 过·≥1天没回·高/中意向 sec_uid 名单)
realtime-touch-table.json评论2话术表(每个 sec_uid → 搬你当初发 ta 的 DM 原文)
dy_cookie.txt你抖音账号的 cookie(监控调接口用)

⚠️ 换池必须同步重生成话术表(雷点⑪)。只换池子不换话术表 → 评论2 退空。

话术怎么出(评论1、评论2 来源完全不同)
评论2(顺产品·搬DM)= 零 LLM、预生成_gen-realtime-touch-table.py 把你当初发 ta 的首触 DM 原文逐字搬进话术表 realtime-touch-table.json(带微信/报价照搬),发评论时按 sec_uid 查表取。换池必须重生成(雷点⑪)否则评论2 退空。
评论1(评视频钩子)= 无影现场 JIT、不预存不在话术表里,由无影本地 _jit_comment1_wuying.py触达当下用 qwen3 看这条视频现场生成一句评视频的钩子;生成空/命中红线词退「赞赞赞」兜底。所以评论1 每条视频现生成、零摆渡、跟视频走。
名单怎么出 + 关注策略
second-touch-worklist.ts(按你 AKKE_ACCOUNT_ID 查库)一次性出全部「已DM未回·高/中意向」候选,跟你现在关注了谁无关(例·野荞 = 276 人 = 168 高 + 108 中)。别做「主页有内容」过滤——要逐个抓 N 个号的主页(撞 7天墙/国内IP)、且空主页天然无害(不发视频→不进关注流→不浪费触达)。按意向优先:先关高意向(GUI 日限 ~30/批,168 人 ≈ 6 天关完),中意向后补。

⚠️ 回复状态必须本机重扫:worklist 的「未回复」靠本机回复扫描数据判定。名单若是别人(PM/fanny)机器生成的,回复状态会是 unknown(没核实)——可能混着已回复过你的人。关注不受影响(照关),但触达前必须在你自己机器跑 scan-dm-replies.py 标出谁回了、回了的剔除/标 stopped,否则可能给正在聊的人又发评论。

3 · 无影端文件清单 全放 C:\akke-wuying\wuying-dm\

脚本 4 个(gitignore,走摆渡):_realtime_touch_watch_wuying.py · _realtime_touch_consume_wuying.py必须带 300s 超时版,雷点③)· douyin_comment_grounded.py必须认「抖音」「douyin」两种标题版,雷点①)· douyin_dm_grounded.py
数据 3 个(§2 摆渡来):special-follow.json · realtime-touch-table.json · dy_cookie.txt
配置.env(见 §4)

4 · .env 必备项(无影本机)

SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
SUPABASE_SCOPED_JWT=...           # role=wuying_worker 受控 JWT,回写直连 Supabase 用
AKKE_ACCOUNT_ID=<你的账号 UUID>
AKKE_ORG_ID=<org UUID>
AKKE_COMMENT_VERIFY_LENIENT=1     # 减评论假失败,必开(雷点⑩)
# 2560×1600 黄金值(饭粒机 06-21 实测验穿、新机直接抄,⚠️别再抄旧部署文档的错值 400,25/220,99):
AKKE_C_SEARCH=432,25  AKKE_C_USERTAB=287,45  AKKE_C_FIRST=219,103  AKKE_C_SEARCH_BTN=589,14  AKKE_C_CLOSE=976,50
# ⚠️ 别设 AKKE_C_LIKE / AKKE_C_WORK_FIRST —— 留空走 VL 视觉定位,固定坐标会点空/开错视频(雷点⑬)
# ⚠️ 坐标改完还得采模板:py douyin_dm_grounded.py --capture(生成 templates\dm_button.png 等,"非主页"兜底+发送键定位要它;模板/坐标都不能跨机复用,雷点⑫)

5 · 启动 · 两个窗口(PowerShell)

监控窗口:

cd C:\akke-wuying\wuying-dm
python _realtime_touch_watch_wuying.py --max-age-min 20 --pool special-follow.json

消费窗口(另开一个):

cd C:\akke-wuying\wuying-dm
python _realtime_touch_consume_wuying.py

摆位:抖音 PC 前台最大化,两个 PowerShell 窗口拖副屏/最小化、别盖在抖音上(雷点⑦)。

5.1 · 🏷️ 给每个窗口命名(带当天日期,强烈建议)

同机常驻多个窗口(监控 / 消费 / DM 派单),长得一模一样,加上天天开新窗口、旧窗口又常忘关,重启/排障时极易杀错或对着死窗口干等。每个窗口在跑脚本【之前】先设标题,标题栏立刻变、串流里一眼区分:

# $(Get-Date -Format 'MMdd') 自动取当天日期 → 标题变 PT监控-饭粒-0622,第二天自动变 0623
$host.UI.RawUI.WindowTitle = "PT监控-饭粒-$(Get-Date -Format 'MMdd')"   # 监控窗口
python _realtime_touch_watch_wuying.py --max-age-min 20 --pool special-follow.json
$host.UI.RawUI.WindowTitle = "PT消费-饭粒-$(Get-Date -Format 'MMdd')"   # 消费窗口(另开)
python _realtime_touch_consume_wuying.py

6 · 验真发(消费日志/返回0 都不可信)

  1. comment_log_YYYYMMDD.csvstatus 列 = sent 才真发;send_unverified/focus_fail/wrong_user/no_msg2 都不算。
  2. executor-runs.log(执行器分阶段落盘)= 看到「♥ 已点赞」+「✅ 评论已验证」才对;一堆「重夺焦点 3 次仍非抖音」= focus_fail(雷点①)。
  3. 铁证(人工):你账号看抖音「喜欢」列表有没有那条视频 + 另一个号/无痕看评论区有没有你的气泡。
  4. 入库:comment_log 摆渡回 mac,跑 pnpm tsx scripts/mark-second-touch.ts --from-comment-log一份只跑一次,非幂等)。

7 · 🔴 雷点清单(全是踩出来的血泪)

① 窗口标题「抖音」/「douyin」因机器而异 → focus_fail
抖音 PC 窗口标题有的机器是中文「抖音」、有的是英文「douyin」(取决于抖音版本/系统语言/重启;同事 4核/8核 不同实例也可能不一样,同一台机重启后也会变)。执行器若只认一个,到另一种机器/重启后就全判「前台不是抖音」→ 整条 focus_fail。所以必须两个都认'抖音' in t or 'douyin' in t.lower())——这是兼容所有机器、不是认错。验:findstr /C:"douyin' in t" douyin_comment_grounded.py

② 监控池文件名不匹配 → 「lead 池不存在」
watch 默认找 special-follow-饭粒.json,你的叫 special-follow.json → 启动必须 --pool special-follow.jsondir special-follow* 看实际名。

③ 执行器无超时 → 一条卡死冻全天
旧版调执行器没超时,一次 GUI 卡住无限等(实测冻 10 小时、全天 0 真发)。用带 AKKE_EXEC_TIMEOUT_SEC(300s)的版本:超时自动 kill+跳过+落盘 executor-runs.log

④ 端点模式 --api-base 不能用(机房连不上 Vercel)
无影到 akke.vercel.app 不通(HTTP 000)。开了不但拉池子每轮失败、领号也失败→把触达全跳过(比本地表模式更糟)。只用本地表模式。

⑤ PowerShell 粘贴长命令/长 URL 会被换行截断
长行常被塞换行 → curl: (2) no URL specified。对策:一行一行单独贴;下大文件用 paste.rs 短链

⑥ 摆渡铁律
一律 curl.exe(带 .exe)写原始字节;别用 iwr/裸 curl(= Invoke-WebRequest,UTF-8 中文会转码弄坏)。下行用 gist raw 直链或 paste.rs 短链;上行 curl.exe -s --data-binary "@文件" https://paste.rs。每次核字节数;paste.rs ~384KB 截断、偶尔 500(重试)。

⑦ 抖音必须真前台 + 触达期间别碰无影桌面
执行器全程控鼠标键盘,你一动就抢前台→点歪/漏字/focus_fail。

⑧ wrong_user:无昵称的「未知客户」搜不到
客户没真昵称(显示「未知客户」)时拿它当搜索词搜不到→落「(非主页)」。✅ 2026-06-18 已修:消费端 resolve_number 把 sec_uid 反查成抖音号填进搜索词(cookie 复用 DM 通道从 DB 取、不落公网)。配机时确认无影 .envSUPABASE_*

⑨ 平台挂起冻住监控(powercfg 管不到)= 头号隐形杀手
powercfg 只关 Windows 层;无影个人版平台层一看「没人在真用这台桌面」就把整台 VM 挂起(powercfg 够不到、个人版无解)。触发 = 远程会话掉:Mac 断网 / Mac 睡 / 连着但久不动鼠标,都会让无影判「空闲」→ 挂起。挂起后监控进程不死、但卡到几乎停——本该每 60s 拉一轮,实测被冻到 6.5 小时才 10 轮、之后彻底无动静,于是逮不到任何新鲜视频(它转太慢,看到时视频都过 20min 了)。⚠️ 症状:进程列表里监控「还活着」、但连续多天 0 触达——别被「进程 alive」骗了,要看监控窗口轮数是不是每分钟+1。
保活三条(都要):① Mac 联网(别断网);② Mac 醒着(caffeinate/LaunchAgent,见前置「关 Mac 休眠」);③ 无影桌面别久闲(连着时隔几分钟动下鼠标)。重启监控后要它全速跑,得趁桌面活跃这一两小时。深夜发布仅 1.8%、接受白天档、保傍晚 17–21 高峰(占 45%)。(实证:2026-06-18/19 连续两天 0 真触达,全是监控被冻——不是没货、不是 cookie 死,cookie 一直好的。)

⑩ VL 验证双向误判:开 LENIENT,别开 TRUST_SEND
VL 既有假阴也有假阳AKKE_COMMENT_VERIFY_LENIENT=1 仍真验证、减假阴——开它。AKKE_COMMENT_TRUST_SEND=1 点了就算、会把真失败刷成功——绝不开

⑪ 换监控池 = 必须重生成话术表
监控池和话术表是两个文件;只换池子不重生成 → 评论2 退空(no_msg2)。看话术表 LastWriteTime 是否晚于最近换池。

⑫ 坐标按本机分辨率实测,换机/重启重测
AKKE_C_* 是 2560×1600 标定的,换机/换分辨率/重启都用 _capture_pos.py 重测。
典型症状(6-17实证):搜人时 OCR 老读到不相干的号(如 @xiexie)、身份门未过→全 wrong_user = 搜索框坐标太靠顶边点空、昵称没输进框→搜空、抖音推个默认号。修:用黄金值(饭粒机 2560×1600 实测 AKKE_C_SEARCH=432,25AKKE_C_USERTAB=287,45AKKE_C_FIRST=219,103)。⚠️ 06-21 血泪:之前 .env 一直是错值 400,25/220,99(抄自旧部署文档,220,99 还和第1条结果重叠点空)+ 缺 dm_button 等模板("非主页"兜底失效),两个叠一起让"搜不对人"卡了好几天。坐标改黄金值后还得 --capture 补采模板主动验:拿一行有抖音号的真名做 CSV 跑 python douyin_comment_grounded.py <test>.csv --confirm,看 [OCR] match=True 落到真人没,到 y/n 答 n 不真发,免等随机触达(06-21 实测「撸铁战士」match=True conf=0.98 验穿)。

⑰ 可达率 ~62%:用户没设抖音号的搜不到、不是 bug
enrich 反查 unique_id(自定义抖音号,字母/dy默认号,搜得到没设就退 short_id(纯数字,如归然 2091195012123230083抖音搜索框搜不到本人、搜出来是随机人、身份门正确跳过)。抽 8 个 lead 实测 5 个能搜、3 个纯数字够不着 → 分母只能是设了号的 ~62%。纯数字那批当前任何搜索通道都无解(要够着得改成从评论直接点进主页,未做)。排障时别把"纯数字用户搜不到"当坐标/模板 bug 修,先 resolve_number 看反查出的是字母号还是纯数字。

⑬ 固定坐标会「点空 / 开错视频」→ 随内容变的元素改 VL(2026-06-18 血泪)
点赞、主页「第一个作品」若用固定坐标(AKKE_C_LIKE/AKKE_C_WORK_FIRST)会出事——点赞点空(爱心没变红)、开视频开错(点到旧视频;归然实例:发到他 6-2 旧视频而非 6-17 新视频)。根因别赖「重启漂移」click_norm 是 0-1000 归一化坐标×屏宽高 = 按比例、分辨率/重启无关、坐标不会自己飘;真因是抖音 UI 随内容变(视频竖屏/横屏→点赞位置不同;主页头部高度→宫格首格位置不同),固定点跟不上。铁证:归然 log 里 VL 视觉定位的(暂停/发送/评论tab)全中、固定坐标的(点赞/首格)全崩。修 = 把 .env 里 AKKE_C_LIKEAKKE_C_WORK_FIRST 两行行首各加 # 注释掉 → 执行器 C_*=None 自动回落已有 VL 分支(找空心爱心/最左上首格),零代码、下条触达自动生效。验:py -c "import douyin_comment_grounded as c; print(c.C_LIKE, c.C_WORK_FIRST)" 应都 None⚠️ 这俩 env DM 也共享(DM 发私信前点赞无 VL 兜底→删后跳过、不影响发私信本身)。

⑭ 进程卫生:旧实例没死透还跑旧代码
改了脚本/配置后,已在跑的 python 进程仍跑内存里的旧代码、改了文件也不生效,必须杀掉重起。起新消费/监控前先 Get-CimInstance Win32_Process -Filter "Name='python.exe'" | Select-Object ProcessId,CommandLine | Format-List 查一眼,旧的 Stop-Process -Id <pid> -Force——别新旧并行(两个消费各跑各的、新旧逻辑混、还可能重复触达)。

⑮ 监控隔夜会挂,每天上班手动重起
_realtime_touch_watch 深夜被无影平台挂起(雷点⑨)后不会自动恢复 → 不重起就一整天零触达、消费空转。每天上班先查进程,没 watch 就重起监控(python _realtime_touch_watch_wuying.py --max-age-min 20 --pool <你的池>)。

⑯ Mac 侧自动化要 caffeinate 保活(跟无影 powercfg 别搞混!两台机
如果你在 Mac 上跑 route-B 相关的长任务(route-A 兜底监控 / mac 侧 ferry / cron 等),Mac 一睡这些就停。让 Mac 永不睡:caffeinate -dimsu &别带 -t 定时,到点会停;不带=永不自停);停用 killall caffeinate⚠️ 扛得住关终端/登出,但扛不住 Mac 重启(重启后重跑,或做 LaunchAgent 开机自起)。别跟无影搞混:无影(Windows)别睡靠 powercfg+平台挂起(雷点⑨),caffeinate 只管 Mac——两台机、两套保活。

8 · 已知未完成(roadmap,别当 bug 报)

相关:项目记忆 docs/claude-memory/project_akke_potential_touch_route_b.md | 对外复盘墙 journeys-fanny#pt