前两天有个做跨境的朋友找我倒苦水。
他在 Mercari 上铺了三十多个号,每个号都要养,每天早上打开电脑第一件事就是挨个登录一遍,验证码、滑块、二次验证,一轮搞下来一个多小时没了。更要命的是有些号隔三差五掉线,掉一次就得重新走一遍流程,搞得他现在看到 Mercari 那个登录页就生理性反胃。
他跟我抱怨的时候我没忍住笑了一下。
不是笑他惨,是笑我自己太懂这种感觉了。
我之前搞过一阵子多账号的东西,那种「明明是个机械动作,但就是得你本人坐在那儿一个个点」的窒息感,真的会把人逼疯。你想自动化,可登录这一步就像一道闸门,死死卡在那儿,过不去后面全是白搭。
后来我就一直在琢磨一件事,登录态这玩意,说到底不就是一串 Cookie 吗。既然是 Cookie,那它就是数据,数据就能被搬运。我为什么不能在一个干净的环境里老老实实登录一次,然后把这一份「登录过的证据」复制到一百个浏览器里去?

我跟你说,这个念头一旦冒出来就收不住了。
然后我就开始翻工具,翻来翻去,翻到一个叫 SyncMeIn 的东西。这玩意不是新面孔了,做跨设备登录态管理的,老玩家应该都听过。它的核心能力就一句话,能稳定抓取并管理跨设备的登录状态,翻译成人话就是,你在一台设备上登录了什么,它能帮你把那份 Cookie 干干净净地掏出来,整理好,打包带走。
当时我第一反应是,这不就是我想要那个「Cookie 提取与分发中枢」吗。
坦率的讲,我一开始也没指望它能跟自动化那套东西接上,毕竟它自己定位是个同步工具,不是给程序员用的。但你想啊,它能导出 JSON 格式的 Cookie 文件,而 JSON 这东西是所有编程语言都认识的通用语,那后面接什么不就随我发挥了。
顺着这个思路往下走,整个链路其实特别清晰。
第一步,在 SyncMeIn 里把目标网站的 Cookie 抓出来。具体操作就是配好代理和抓包环境,然后在目标设备上正常访问一下目标网址,触发脚本捕获。日志里确认抓取成功之后,用它的导出功能,存成 cookies.json 扔到本地。
第二步,把这个 JSON 喂给 Puppeteer。
说到 Puppeteer,可能有些小伙伴没接触过,简单讲就是 Google 出的一个 Node.js 库,能让你用代码控制 Chrome 浏览器,点页面、填表单、截图、爬数据,啥都能干。它有一个特别关键的 API 叫 page.setCookie(),看名字就懂了,批量往页面里塞 Cookie。
把这两步接起来,会发生什么?
你在一个真实设备上,用真人的手指头,老老实实登录一次。然后把这次登录的「成果」导出来,啪一下灌进一百个无头浏览器里。那一百个浏览器瞬间全部变成「已登录状态」,不用再过验证码那道鬼门关。

想想就觉得兴奋。
我先把核心代码贴出来,你感受一下这个流程有多短。
const puppeteer = require('puppeteer-core');
const fs = require('fs');
(async () => {
// 连接到已经启动的浏览器实例,别频繁启动,那是烧资源
const browser = await puppeteer.connect({
browserWSEndpoint: 'ws://localhost:5000/ws/automation'
});
// 读取 SyncMeIn 导出的 Cookie
const cookies = JSON.parse(fs.readFileSync('./cookies.json'));
// 创建新页面,注入 Cookie
const page = (await browser.pages())[0] || await browser.newPage();
await page.setCookie(...cookies);
// 访问受保护页面,验证 Session 是否恢复
await page.goto('https://目标网站.com/dashboard');
console.log('登录状态已恢复');
// 断开连接,注意是 disconnect 不是 close
await browser.disconnect();
})();
就这么点东西。
你可能纳闷,就这么几行代码,能干啥?
我跟你说,就这么几行代码,干掉的是我那个朋友每天早上一小时的重复劳动。
但这里头有几个坑,我必须提前跟你交代清楚,不然你照着抄一遍跑不通,回头还得骂我。
第一个坑,连接方式。
你看我代码里用的是 puppeteer.connect(),不是 puppeteer.launch()。这俩看着差不多,实际天差地别。launch 是你自己启动一个全新的浏览器,connect 是连到一个已经在跑的浏览器上。
为啥这么讲究?
因为如果你在一个 Agent 沙箱环境里跑,用 launch 启动一个新浏览器,跑完 close 掉,那之前所有的状态,Cookie、localStorage、缓存,全没了。下一次任务再启动,又是白纸一张,你注入的 Session 跟没注入一样。
正确的姿势是,浏览器一直在后台跑着,你的脚本只是连上去干活,干完 disconnect 走人,浏览器原封不动留在那儿,下一个任务接着连。
这个区别看着小,实际是「能跑通」和「跑一次就废」的分水岭。
第二个坑,Cookie 完整性。
page.setCookie() 这个 API 看着简单,但它对 Cookie 的字段要求特别挑剔。domain、path、secure、httpOnly,一个都不能少,而且注入顺序还得对。
我第一次跑的时候就是栽在这上面,导出来的 JSON 少了几个字段,注入进去看着成功了,一访问页面立马被打回登录页。查了半天才发现是 httpOnly 那个标志位没带上,目标网站在校验。
所以导出那一步,一定要确认 SyncMeIn 给你的 JSON 是完整的,别图省事删字段。
第三个坑,文件路径。
这个听着更琐碎,但在沙箱环境里是真的会要命。Cookie 文件必须放在有读写权限的目录下,比如 /home/user/data/ 这种,别扔到什么系统目录或者临时目录里,跑着跑着权限报错,你都不知道哪儿出了问题。

回到多开这块再聊聊。
上面那段代码是单开,一个浏览器一个页面注入一份 Cookie。但你真正要干的事肯定是批量,我那个朋友是三十多个号,有人可能是一百个、五百个。
这时候最容易犯的错就是,一个号启动一个 Chrome 实例。
你试试就知道了,开到第二十个的时候你电脑风扇就开始惨叫,开到第五十个系统基本就躺平了。每个 Chrome 实例都是几百兆内存起步,这玩意不是这么玩的。
正确的架构是,单浏览器加多上下文。
Puppeteer 有个 API 叫 createIncognitoBrowserContext(),翻译过来就是创建一个隐身上下文。每个隐身上下文都有自己独立的 Cookie 和 localStorage,互相之间完全隔离,但它们共享同一个 Chrome 进程,内存开销极低。
一个 Chrome 实例,开一百个隐身上下文,比你开一百个 Chrome 实例省下来的资源,是数量级的差距。
然后再加上任务池和并发控制。有个库叫 puppeteer-cluster,专门干这个的,帮你管任务队列,控制同时跑多少个。我个人建议并发数卡在 50 到 100 之间,既不把资源压垮,又能保证吞吐量。
最后还有一件事特别容易被忽略,清理。
多开环境下,每次任务跑完,必须把 Page 关掉、Context 清掉。听着像废话,但你跑个三天三夜不重启就会发现,内存曲线一路往上爬,最后 OOM 直接挂掉。这种 bug 查起来能让人脱一层皮,因为它不是逻辑错误,是资源泄漏,平时看不出来,攒到一定量才爆。
养成习惯,任务结束的 finally 块里,该关的关,该清的清,别偷懒。
说到这儿,技术层面基本讲完了。但有一件事我必须单独拎出来讲,因为它比上面所有技术细节都重要。
风控。
你想想看,一个账号平时都在东京某个 IP 上活动,突然之间,五分钟内从上海、新加坡、法兰克福三个地方同时登录,你觉得平台的风控系统会怎么想?
它不会觉得你是为了效率,它只会觉得这个号被盗了。

我那个朋友最早就吃过这个亏。他用 SyncMeIn 抓了一批 Mercari 的 Session,灌到 Puppeteer 里批量跑,结果第二天一睁眼,三十多个号封了一半。
后来他摸出来一个规律,Mercari 这种平台对 iOS 设备的 Session 权重和信任度明显更高。也就是说,你用 iPhone 上的 Mercari App 登录抓出来的 Cookie,比你在电脑 Chrome 上登录抓出来的 Cookie,能活得更久,能扛更多异设备接入。
为啥?因为 iOS 设备的指纹更稳定,平台觉得「这人在自己手机上登录」这件事可信度更高,给的信任额度也就更大。
所以后来他改了流程,先用一台 iPhone 老老实实把每个号登录一遍,再用 SyncMeIn 把 iOS 端的 Cookie 抓出来,然后再分发到 Puppeteer 集群里。封号率从一半掉到了个位数。
这个细节没有任何文档会告诉你,全是拿号试出来的。
我有时候觉得,做自动化这事,技术其实只占三成,剩下七成是在跟平台的风控团队博弈。你每找到一个绕过的办法,他们那边就多加一道检测,你再加一层伪装,他们再升一级模型。这就是一场军备竞赛,没有终点的那种。
这让我想起一个词,黑暗森林。
刘慈欣在《三体》里写的那个宇宙社会学,每個文明都是带枪的猎人,在黑暗森林里悄悄潜行,谁先暴露位置谁就被消灭。
放到自动化这个场景里,平台是猎人,你也是猎人。平台在暗处布下无数检测规则,等着自动化脚本自投罗网,你在暗处一遍遍试探边界,找到一条能过的路就赶紧走,走完这条路大概率也就废了,得找下一条。
谁都不能把所有底牌亮出来,亮出来就是死。
这种博弈格局,注定了做自动化的人永远没法躺平。你今天跑通的东西,明天可能就失效,后天平台换了一套风控模型,你前功尽弃。所以真正能长期活下来的玩家,不是技术最强的,而是最敏感的,能第一时间感知到风向变化,第一时间调整策略。
我那个朋友现在每天早上第一件事不是登录账号了,改成看封号率。封号率突然跳一下,他就知道平台又更新规则了,得停下来研究,不能闷头往前冲。
这其实是一种很特别的生存智慧。
你想想看,我们这一代做互联网的人,习惯了「规则是确定的」这种思维。API 文档写清楚了你照着调就行,框架更新有 changelog,出了 bug 有 Stack Overflow。整个开发者生态是建立在「透明」这个前提上的。
但风控这块不是。风控规则是平台的核心资产,他们恨不得你一点都不知道。你在跟一个不透明的对手博弈,所有的经验都只能靠踩坑积累,靠号换。
这就是为什么我特别尊重那些在自动化领域活下来的老玩家。他们手里的经验,没有一条是 Google 搜得到的,全是真金白银砸出来的。

说真的,写这篇的时候我有点感慨。
SyncMeIn 加 Puppeteer 这套组合,技术上看一点都不复杂,会写 Node.js 的人半小时就能跑通。但真正把它用好的那批人,背后付出的远不止半小时。他们踩过的封号坑、调过的并发数、摸过的设备权重,这些东西永远不会写进任何教程。
工具是公开的,经验是私有的。
这大概就是这一行最残酷也最迷人的地方。
最后我想给看到这儿的朋友一个建议。
如果你也在做多账号、自动化这类事情,别光盯着技术方案看,技术方案网上大把。多花点时间研究平台的脾气,研究风控的边界,研究什么设备、什么 IP、什么行为模式更容易被信任。这些东西才是真正决定你能不能长期跑下去的关键。
至于代码层面,我上面贴的那套已经够你起步了。先单开跑通,再多开压测,再上集群,一步一步来,别一上来就想搞五百个并发,那样你连问题出在哪都查不出来。
哦对了,还有个事差点忘了说。
如果你手头有具体的多开场景想让我帮你写一份 puppeteer-cluster 的并发控制配置示例,比如任务队列怎么排、并发数怎么动态调、失败重试怎么搞,评论区吱一声,我可以单独再写一篇把这个展开讲。
这种东西展开讲能讲一整篇,塞在这儿就太挤了。
我始终坚信,工具的价值不在于它本身多强大,在于用工具的人愿不愿意把那些枯燥的、没人看见的细节啃下来。SyncMeIn 给你的是一把刀,Puppeteer 给你的是一只手,但这一刀砍向哪儿、砍多深,永远是你自己说了算。
注意,本项目仅在 SyncMein 的500人小群分享。
加微入群,谢谢你看完了我的文章,我们下次再见吧。
/ 作者:明察
/ 投稿或爆料,请联系邮箱:mingcha@gqmg.com












暂无评论内容