做TikTokShop多店铺的团队,十个有九个问过同一个问题:每个店都单独配了代理,注册资料也全部分开,为什么还是被判成关联?我的结论是,多店铺被判定关联,绝大多数情况不是某一项没做到位,而是多条链路同时露出了同一性。
平台侧的判定逻辑从来不是单点匹配,而是把主体资料、商品素材、网络出口、设备身份、操作行为这些维度叠在一起看,任何一条链路单独看都问题不大,但当两三个店铺在四五个维度上同时撞车,模型给出的置信度就足够触发人工复核甚至直接限制店铺。
这也是为什么很多人"该做的都做了"却依然翻车:他们通常在业务资料层做了拆分,却在网络与设备层偷懒;或者反过来,把代理和指纹环境配得极其讲究,回头五家店共用同一个收款账户、同一套客服邮箱、同一批主图素材。
真正在这一行跑得稳的团队,做的一定是分层治理:前面两层靠业务设计解决,后面两层靠技术环境解决,只做一半都会出问题。
一、多店铺被判定关联,通常是"多条链路同时撞车"
把关联信号拆成四层来看,思路会清楚很多。
层级 |
具体维度 |
归属 |
典型失误 |
经营主体层 |
公司主体、税务号、银行账户、注册地址、联系电话、联系邮箱 |
业务设计 |
两家店共用同一个收款账户或同一个客服邮箱 |
商品与内容层 |
类目结构、主图与详情图、文案模板、定价逻辑、SKU命名规则 |
业务设计 |
五家店主图来自同一套素材库,去掉水印后直接复用 |
网络与设备层 |
出口IP段、浏览器指纹(Canvas/WebGL/AudioContext)、移动端设备身份(IMEI、AndroidID、GAID) |
技术环境 |
换IP不换环境,或者换环境不换IP |
行为与运营层 |
登录时段、操作节奏、客服话术模板、发货时效、售后处理模式 |
业务加技术 |
三家店每天9:00到9:15由同一人按同样顺序登录处理订单 |
这四层里,前两层完全是业务问题,跟技术工具没什么关系。税务号是不是独立的、收款账户有没有共用、客服邮箱是不是一个前缀换后缀、主图是不是同一批摄影师按同一套模板拍的,这些东西平台拿数据一比对就能看出来,任何指纹环境都救不回来。
后两层才是技术环境能覆盖的范围。出口IP是不是同一个段、浏览器指纹里的十几个字段是不是撞了、移动端读取的IMEI和传感器是不是同一台设备、DNS请求有没有走代理,这些属于"设备身份"层面的东西。
行为层比较特殊,它一半是业务制度问题(谁在什么时候登哪几个店、话术模板是不是一份),一半是技术环境问题(操作节奏有没有随机性、同步操作有没有留痕)。很多团队出问题就出在这一层:环境和代理都做得挺好,但团队五个人每天早上集中在一小时内把二十个店全登一遍,操作顺序还一模一样。
所以判断自己的多店铺体系安不安全,别问"我用了什么工具",先问"这四层里,我在哪几层露了同一性"。
二、TikTokShop的特殊性:为什么它比传统货架电商更难
2.1移动优先:App端多出来的一整层设备身份
TikTokShop和亚马逊、eBay这类货架电商一个很明显的区别在于,它的流量主场景在App端。卖家后台虽然是网页,但店铺号、达人号、内容号的日常运营大量发生在手机App里,而App能读到一整层网页端根本拿不到的东西。
维度 |
网页端可覆盖 |
仅移动端可覆盖 |
说明 |
User-Agent |
是 |
是 |
移动端UA需与具体机型匹配 |
Canvas/WebGL/AudioContext |
是 |
部分 |
App内嵌WebView同样会采集 |
屏幕分辨率、色深、设备像素比 |
是 |
是 |
移动端需匹配真实机型面板参数 |
字体列表 |
是 |
否 |
移动端字体集由系统镜像决定 |
时区、语言 |
是 |
是 |
需与SIM归属国、IP归属地一致 |
IMEI/MEID |
否 |
是 |
需通过真实Android实例还原 |
MAC地址 |
否 |
是 |
模拟器常露出虚拟化固定段 |
AndroidID/GAID |
否 |
是 |
应用层可读,重置行为本身也是信号 |
基带版本、运营商、SIM信息 |
否 |
是 |
会与IP归属地做交叉校验 |
传感器列表与数值(加速度、陀螺仪、光线) |
否 |
是 |
模拟器常返回空列表或全零 |
电池状态、充电状态、温度 |
否 |
是 |
恒定值或全零属于异常 |
GooglePlay兼容性与推送通道 |
否 |
是 |
直接影响App功能完整度 |
这张表看明白之后,一个常见误区就站不住了:很多团队给每个店铺配了独立浏览器环境,后台登录链路做得干干净净,但运营同学手机上装了五个TikTok客户端来回切,或者用一台x86模拟器跑十个号,结果移动端那一整层设备身份全撞在一起。后台做得再好也没用,因为平台看到的是同一个人拿着同一台手机在不同账号之间反复横跳。
2.2内容与账号强绑定:账号之间本身就是一张关系图
TikTokShop的店铺号、达人号、内容号之间经常互相导流,这种设计天然形成一张关系图。A店铺绑定的达人号去给B店铺带货,两个店之间的连线就建立了;一批内容号同时关注、评论、转发同一个店铺号,权重就往一起聚。
这意味着TikTok系的关联判定不只是"看参数像不像",还在看"你们之间有没有关系"。两个店铺的浏览器指纹完全不同、出口IP分属两个大洲,但如果它们的带货达人号高度重合、评论区互动账号高度重合,一样会被画进同一个簇。
所以内容层的账号也要做环境隔离,不能只管店铺号。达人号、内容号同样需要一号一环境、一号一IP,冷启动期也要分开走。
2.3账号受限的高频成因
从行业里收集到的情况看,TikTok系账号被限制的原因大致集中在四类:
成因类别 |
具体表现 |
归属 |
网络环境不稳定 |
短时间集中注册、频繁掉线、视频上传中断、登录地跳变 |
技术环境 |
资格不合规 |
主体资质不全、年龄或地区资格不符、资料真实性存疑 |
业务设计 |
同设备多账号 |
一台手机或一个环境登录多个账号 |
技术环境 |
内容违规 |
版权素材、低质内容、违禁品类、社区规则违反 |
业务设计 |
头一类是容易被忽视的。很多人以为只要IP换了就安全,但从平台视角看,一个账号三天内从三个国家的IP登录、上传视频传一半断了五次,这种"网络环境质量差"本身就是强信号,和它是不是独立IP没有关系。环境的稳定性比多样性更重要,后面3.5会展开讲。
2.4同一出口IP下的账号数量约束
行业里一个流传很广的经验值是:同一出口IP下不宜超过3个账号。这个数字没有官方出处,是运营者长期踩坑总结出来的,但它背后的逻辑说得通。真实世界里一个家庭宽带或一个小办公室出口,同时活跃三五个电商卖家账号的概率不高,超过这个量级,出口的行为画像就开始偏离正常用户分布。
更关键的是,单纯换IP在TikTokShop场景已经不够了。原因有三:
一是IP只是网络层,设备身份层的指纹、移动端IMEI和传感器这些维度IP完全覆盖不到。
二是平台会看IP的历史行为。一个刚被几十个账号轮换使用过的IP,信誉度远低于一个长期稳定绑定某一个账号的住宅IP。
三是频繁换IP本身就是信号。今天洛杉矶、明天新加坡、后天法兰克福,从平台角度看这不是"多地区运营",而是"环境不稳定"。
正确的做法是:一号一IP,IP与环境固定绑定,IP归属地、时区、语言、SIM运营商国别四者保持一致,且长期不变。
三、环境隔离的四个技术面
3.1设备身份面:指纹怎么被采集,参数怎么做到自洽
网页端指纹的采集原理说穿了不复杂:页面跑一段JS,调用浏览器暴露的各种API,把返回值拼起来做哈希。Canvas是让浏览器画一段固定文字或图形,然后toDataURL()把像素取出来,不同显卡、不同驱动、不同字体渲染出来的像素有细微差异;WebGL除了走同样的路子,还能通过getParameter()拿到renderer和vendor字段,直接暴露GPU型号;AudioContext是跑一段音频信号处理,取输出缓冲区的值,音频栈不同结果就不同;WebRTC的ICE候选收集过程会顺带把本地和公网IP露出来;字体列表靠逐个测量字符宽度判断某个字体是否安装;剩下UA、分辨率、色深、时区语言、硬件并发数、deviceMemory则是直接读navigator和screen的属性。
采集容易,难的是让这些参数之间自洽。一堆随机生成的参数拼在一起,单看每一个都正常,放一起就互相打架。下面这张表是我日常做环境验收时必查的约束关系:
序号 |
约束关系 |
不自洽的典型表现 |
1 |
UA中的操作系统↔navigator.platform |
UA写Windows,platform露出MacIntel |
2 |
UA内核版本↔userAgentData中的版本号 |
大版本对不上 |
3 |
屏幕分辨率↔设备像素比↔色深 |
1920x1080配DPR3 |
4 |
分辨率↔可用视口高度 |
忽略了任务栏高度,availHeight等于height |
5 |
时区↔IP归属地↔SIM运营商国别 |
IP在德国,时区是Asia/Shanghai |
6 |
语言列表↔Accept-Language请求头 |
两者顺序或内容不一致 |
7 |
硬件并发数↔内存↔机型定位 |
32核配4GB内存 |
8 |
deviceMemory↔机型档位 |
低端机型配32GB内存 |
9 |
WebGLrenderer↔vendor↔UA声明的GPU平台 |
renderer是AppleGPU但UA是Windows |
10 |
Canvas噪声↔同一环境多次采样 |
每次刷新结果都变,反而不自然 |
11 |
字体列表↔操作系统版本 |
Windows环境列出只有macOS才有的字体 |
12 |
WebRTC候选地址↔代理出口IP |
候选里出现本地真实内网IP |
13 |
AudioContext输出↔声明的音频栈 |
与系统组合不匹配 |
14 |
时区偏移量↔夏令时规则 |
美东IP但偏移量不含夏令时调整 |
这里有个关键的工程差异值得单独说:市面上做指纹处理基本有两条路,一条是在渲染引擎源码层直接改写采集API的返回值,另一条是在页面加载时注入JS脚本覆盖navigator之类的对象。后者成本低、见效快,但有个绕不过去的毛病,就是它覆盖的是JS层面,而WebGL的像素、Canvas的像素、音频缓冲区的数值是在引擎内部算出来的,注入脚本很难让它跟覆盖后的字段保持一致;而且注入脚本本身会改变JS执行栈,检测方抓一下函数toString或者看一眼调用栈就能发现。
源码层改写(比如基于Chromium定制分支,在C++层面对Canvas、WebGL、WebRTC、AudioContext这几个API做hook)的好处是指纹数值和浏览器其余行为天然自洽,不会出现"UA说Windows但别处露出macOS"这种自相矛盾。这也是评估这类工具时值得重点关注的一点。
3.2存储隔离面:为什么"清缓存"不能替代隔离
一个浏览器环境里跟身份相关的存储有六类:Cookie、LocalStorage、SessionStorage、IndexedDB、HTTP缓存、以及整个用户数据目录(UserDataDirectory)。平台会把设备标识、会话票据、行为埋点写进这些地方,其中IndexedDB和LocalStorage因为容量大、生命周期长,是写入持久化标识的重灾区。
很多人的做法是开无痕窗口或者定期清缓存,这在多店铺场景下基本没用。原因有两个:一是清理不彻底,ServiceWorker缓存、HTTP缓存分区、以及某些应用写入的IndexedDB子库常常被漏掉;二是清理行为本身就是异常的,一个每天登录卖家后台的商家账号,每次登录都是全新Cookie、全新LocalStorage,这个模式在真实用户里非常罕见。
正确的做法是Profile级隔离:每个账号一个独立的用户数据目录,Cookie、LocalStorage、Session、IndexedDB、缓存、代理隧道全部按目录分开,环境之间没有任何共享路径。环境一旦建好就长期持有,不做清理,让它像一个用了两年的真实浏览器一样积累数据。
3.3网络链路面:代理类型怎么选,泄漏从哪来
代理类型 |
出口特征 |
TikTokShop场景取舍 |
主要风险 |
住宅代理 |
来自真实家庭宽带,ISP归属清晰 |
卖家后台与日常运营的主力选择 |
部分资源为共享池,需确认是否独享 |
移动代理 |
来自蜂窝网络,IP段归属运营商 |
与App端运营天然匹配,适配移动端实例 |
单价高,IP轮换频率需控制 |
数据中心代理 |
来自机房,ASN归属为云厂商 |
适合非核心的后台查询类任务 |
与真实用户网络差异明显,核心账号不建议用 |
网络层有两个老生常谈但总有人踩的坑:DNS泄漏和WebRTC泄漏。
DNS泄漏的成因是浏览器或操作系统在解析域名时没有走代理隧道,直接用本地DNS服务器发起了查询。结果就是你以为自己从洛杉矶上网,但DNS查询暴露了你在深圳。解决方式是让DNS解析随代理走,禁用本地DNS回退,验收时用DNS泄漏检测站点看列出的解析服务器归属。
WebRTC泄漏的成因是ICE候选收集。即使你开了代理,WebRTC在建立连接的过程中依然会收集本地网络接口的候选地址,包括内网IP和真实公网IP,一段JS就能把这些值读出来。解决方式是关闭WebRTC或者强制它只走代理出口,验收时看候选地址里有没有出现本地IP段。
3.4移动端身份面:真实Android实例和x86模拟器差在哪
这一节是TikTokShop场景的重头戏。移动端环境有两条技术路线:云端真实Android实例和x86模拟器。
对比项 |
真实Android云实例 |
x86模拟器 |
IMEI/MEID |
由机房实体设备的芯片参数还原 |
多为固定值,或可写但易被识别 |
MAC地址 |
与实体网卡绑定 |
常见虚拟化固定段 |
基带版本 |
与机型一致 |
常为空或Unknown |
SIM与运营商 |
支持600+全球运营商配置 |
多数无法配置 |
传感器 |
有真实量程与噪声 |
返回空列表或全零 |
电池与充电状态 |
有真实变化曲线 |
恒定值 |
GooglePlay与推送 |
原生支持,可一键下载海外应用 |
需手动注入,兼容性不稳定 |
ADB与root |
可授权,便于脚本化配置 |
视镜像而定 |
指令集兼容性 |
ARM,与真机一致 |
x86需翻译层,部分App直接无法运行 |
差异是全方位的,真要挑出要命的地方,是这三处:传感器、运营商、指令集。
传感器这块,真实设备的加速度计和陀螺仪即使在静止状态也有细微噪声,光线传感器有量程和分辨率,而模拟器通常返回一个空列表或者一串全零。App只要遍历一次SensorManager就能判断。
运营商这块,支持600+全球运营商配置的价值在于,你可以让一台设备的SIM信息、MCC/MNC、APN配置和出口IP的归属地完全对应,包括欧洲、美洲、东南亚的一些小众运营商。模拟器的SIM信息基本是空的,App读到null就知道不对劲。
指令集这块,很多海外App只发布了ARM架构的native库,在x86模拟器上要么跑不起来,要么走二进制翻译导致性能极差、行为异常。
所以移动场景我的建议很明确:用真实Android实例,不要用模拟器。像MostLogin提供的云手机这类产品走的就是真实实例路线,一台云手机对应一个完整的移动端环境,参数跟着实体设备的芯片走,也支持ADB与root权限做脚本化配置。
3.5一个关键工程原则:持久性优先于"多变"
这一条单独拿出来讲,因为它是新手特别容易搞反的地方。
很多人以为环境越随机越好,于是给每个环境开随机指纹,每次启动都换一套参数,代理池一天轮三次。从平台风控的角度看,这个行为模式非常刺眼:一个真实商家的浏览器,两年里UA变过两三次(跟着浏览器自动升级),IP可能几个月不动一次,时区语言从来不变。而你的账号一周变八次指纹、一天换三个国家的IP,这叫"环境不稳定",是2.3里提到的高频受限成因之一。
正确的原则是:环境的持久性与稳定性优先于多变。参数一旦配好就固定下来,代理与环境长期绑定,指纹只在浏览器内核大版本升级时跟着走。多变应该体现在"不同环境之间不一样",而不是"同一个环境每次不一样"。
四、多店铺环境隔离的架构设计
4.1四要素映射表
先建立一张"店铺、环境、代理、负责人"的映射表,这是整个体系的骨架。下面是一份10个店铺的样表:
店铺编号 |
站点 |
浏览器环境名 |
移动端实例 |
代理归属地 |
代理类型 |
负责人 |
TS-01 |
美国 |
TTSHOP-US-01 |
CP-US-01 |
洛杉矶 |
住宅独享 |
张三 |
TS-02 |
美国 |
TTSHOP-US-02 |
CP-US-02 |
芝加哥 |
住宅独享 |
张三 |
TS-03 |
英国 |
TTSHOP-UK-01 |
CP-UK-01 |
伦敦 |
住宅独享 |
李四 |
TS-04 |
英国 |
TTSHOP-UK-02 |
CP-UK-02 |
曼彻斯特 |
住宅独享 |
李四 |
TS-05 |
马来西亚 |
TTSHOP-MY-01 |
CP-MY-01 |
吉隆坡 |
住宅独享 |
王五 |
TS-06 |
马来西亚 |
TTSHOP-MY-02 |
CP-MY-02 |
槟城 |
住宅独享 |
王五 |
TS-07 |
泰国 |
TTSHOP-TH-01 |
CP-TH-01 |
曼谷 |
移动代理 |
王五 |
TS-08 |
越南 |
TTSHOP-VN-01 |
CP-VN-01 |
胡志明市 |
移动代理 |
赵六 |
TS-09 |
印尼 |
TTSHOP-ID-01 |
CP-ID-01 |
雅加达 |
住宅独享 |
赵六 |
TS-10 |
菲律宾 |
TTSHOP-PH-01 |
CP-PH-01 |
马尼拉 |
住宅独享 |
赵六 |
几个约定:一个店铺对应一个浏览器环境和一个移动端实例,禁止跨店复用;一个环境绑定一条固定代理,禁止切换;一个负责人可以管多个店,但同一时段的并发操作要有节奏控制。
4.2环境配置清单表
参数项 |
推荐策略 |
原因 |
User-Agent |
与真实机型加系统版本一一对应,跟随内核版本升级 |
UA与内核版本脱节是常见破绽 |
屏幕分辨率与色深 |
使用目标市场主流机型档位 |
极端分辨率占比过高会显得不自然 |
时区与语言 |
与代理IP归属地、SIM运营商国别三者一致 |
三者不一致属于高风险组合 |
Canvas/WebGL |
开启噪声,但保持同一环境内稳定 |
每次都在变反而异常 |
WebRTC |
关闭或强制走代理出口 |
避免真实IP泄漏 |
字体列表 |
与声明的操作系统版本匹配 |
混用系统字体会露馅 |
硬件并发与内存 |
与机型定位匹配 |
满足参数自洽性约束 |
代理协议 |
HTTP(S)/SOCKS5,一号一IP固定绑定 |
环境切换IP等于自我暴露 |
DNS |
随代理走,禁用本地DNS回退 |
避免DNS泄漏 |
用户数据目录 |
每环境独立,禁止跨环境复制 |
存储隔离的基础 |
4.3分阶段落地路径
第一阶段,主体与资料层梳理。把每个店铺的公司主体、税务号、银行账户、地址电话、联系邮箱列成一张表,做交叉比对,任何两项共用就先解决。这一步不写代码、不配环境,但它决定了后面所有技术投入的上限。
第二阶段,环境批量创建与绑定。按4.1的映射表批量建环境,命名规则统一,业务元数据(店铺编号、站点、负责人)写进环境的备注字段或者外部台账。
第三阶段,代理池规划。按店铺数量和目标站点采购代理,优先住宅独享,移动端实例配移动代理。每条代理在采购时就和环境做绑定登记,不搞动态池。
第四阶段,团队权限与操作日志。按4.4的角色划分分配权限,强制开启操作日志,日志至少保留90天。
第五阶段,日常巡检。按4.5的清单按周按月跑,出问题能追溯。
4.4团队权限设计
角色分四层:管理员、店铺负责人、操作员、只读审计。
操作 |
管理员 |
店铺负责人 |
操作员 |
只读审计 |
创建或删除环境 |
是 |
否 |
否 |
否 |
修改代理绑定 |
是 |
是 |
否 |
否 |
启动或停止环境 |
是 |
是 |
是 |
否 |
登录店铺后台 |
是 |
是 |
是 |
否 |
修改收款信息 |
是 |
是 |
否 |
否 |
查看操作日志 |
是 |
是 |
否 |
是 |
导出环境配置 |
是 |
否 |
否 |
否 |
分配成员权限 |
是 |
否 |
否 |
否 |
权限设计的原则是按需分配、够用即可。操作员只给他日常要用的那几个店,不要让所有人都能看到全部店铺,这不是不信任团队,而是出事时能缩小排查范围。配置分享功能可以在不暴露原始登录凭证的前提下把指定环境共享给成员,比直接发账号密码安全得多。
4.5日常巡检清单
周期 |
巡检项 |
判定标准 |
每周 |
抽样3个环境跑指纹报告比对 |
关键字段无重复 |
每周 |
代理连通性与出口IP核对 |
出口IP与绑定记录一致 |
每周 |
WebRTC与DNS泄漏检查 |
无本地真实IP与本地DNS出现 |
每周 |
登录时段与操作日志抽查 |
无跨环境同一时段同人密集操作 |
每月 |
店铺主体资料复核 |
无跨店共用的账户、邮箱、电话 |
每月 |
商品与素材相似度抽查 |
跨店主图与文案不重复 |
每月 |
移动端实例参数复核 |
机型、运营商、传感器数值正常 |
每月 |
成员权限复核 |
离职成员权限已回收 |
五、操作示例
下面三段代码都是示意,接口路径和字段名以当前客户端版本的官方文档为准。
示例A:本地API批量创建店铺环境并写入业务元数据
#-*-coding:utf-8-*-
"""
批量创建TikTokShop店铺环境,并写入业务元数据
注意:接口路径与字段名以当前客户端版本的官方文档为准
"""
importtime
importrandom
importrequests
BASE="http://127.0.0.1:30898"
TOKEN="YOUR_MOSTLOGIN_TOKEN"#授权值等同密码,不要提交到代码仓库
HEADERS={
"Content-Type":"application/json",
"Authorization":"Bearer"+TOKEN,
}
#本地API限速:基础版2/秒、进阶版5/秒、专业版10/秒、企业版20/秒
#这里按5/秒做上限,并留出安全余量
RATE_PER_SEC=4.0
_last_call=0.0
def_throttle():
"""简易限速器:保证两次调用之间的间隔不小于1/RATE_PER_SEC"""
global_last_call
interval=1.0/RATE_PER_SEC
wait=interval-(time.time()-_last_call)
ifwait>0:
time.sleep(wait)
_last_call=time.time()
def_request(method,path,payload=None,retries=3):
"""带指数退避的重试封装,只对可恢复的错误重试"""
last_exc=None
forattemptinrange(retries):
_throttle()
try:
resp=requests.request(
method,
BASE+path,
headers=HEADERS,
json=payload,
timeout=15,
)
#429触发限速,5xx属于服务端抖动,两者都可重试
ifresp.status_code==429:
time.sleep(2**attempt+random.uniform(0,0.5))
continue
if500<=resp.status_code<600:
time.sleep(2**attempt)
continue
ifresp.status_code>=400:
#4xx多为参数或权限问题,重试没有意义,直接抛出
raiseRuntimeError(
"请求失败%s:%s"%(resp.status_code,resp.text[:300])
)
returnresp.json()
exceptrequests.exceptions.RequestExceptionasexc:
last_exc=exc
time.sleep(2**attempt)
raiseRuntimeError("重试耗尽:"+path)fromlast_exc
#店铺台账:真实项目里建议从外部表格或数据库读取,不要硬编码
SHOPS=[
{"shop_id":"TS-01","site":"US","proxy":"http://user:pass@la-proxy:8080",
"tz":"America/Los_Angeles","lang":["en-US"],"owner":"张三"},
{"shop_id":"TS-02","site":"US","proxy":"http://user:pass@chi-proxy:8080",
"tz":"America/Chicago","lang":["en-US"],"owner":"张三"},
{"shop_id":"TS-03","site":"UK","proxy":"http://user:pass@lhr-proxy:8080",
"tz":"Europe/London","lang":["en-GB"],"owner":"李四"},
]
defbuild_payload(shop):
"""把台账里的一行记录组装成创建环境的请求体"""
return{
"name":"TTSHOP-%s-%s"%(shop["site"],shop["shop_id"].split("-")[1]),
"group":"TikTokShop/%s"%shop["site"],
#业务元数据写进remark,方便后续按店铺反查环境
"remark":"shop=%sowner=%s"%(shop["shop_id"],shop["owner"]),
"proxy":{"type":"http","host":shop["proxy"]},
"fingerprint":{
"timezone":shop["tz"],
"language":shop["lang"],
"webrtc":"disabled",#关闭WebRTC,避免真实IP泄漏
"dnsFollowProxy":True,#DNS随代理走,避免DNS泄漏
},
}
defmain():
created=[]
forshopinSHOPS:
try:
data=_request("POST","/api/v1/profile/create",build_payload(shop))
created.append((shop["shop_id"],data.get("data",{}).get("id")))
print("已创建%s"%shop["shop_id"])
exceptExceptionasexc:
#单条失败不影响整批,记录下来后续补跑
print("创建失败%s:%s"%(shop["shop_id"],exc))
print("完成%d/%d"%(len(created),len(SHOPS)))
if__name__=="__main__":
main()
示例B:环境自检脚本,比对多个环境的指纹字段
#-*-coding:utf-8-*-
"""
批量读取各环境的指纹字段并比对,输出成表格
依赖:playwright(pipinstallplaywright&&playwrightinstallchromium)
思路:本地API启动配置拿到debugport,再用connect_over_cdp挂上去取值
"""
importrequests
fromplaywright.sync_apiimportsync_playwright
BASE="http://127.0.0.1:30898"
TOKEN="YOUR_MOSTLOGIN_TOKEN"
HEADERS={"Content-Type":"application/json","Authorization":"Bearer"+TOKEN}
PROFILE_IDS=["TTSHOP-US-01","TTSHOP-UK-01","TTSHOP-MY-01"]
#在页面上下文里执行的采集脚本,覆盖8类常用指纹维度
COLLECT_JS="""
()=>{
constc=document.createElement('canvas');
constctx=c.getContext('2d');
ctx.fillText('fingerprintself-check12345',10,40);
constcanvasHash=c.toDataURL().slice(-64);
constgl=document.createElement('canvas').getContext('webgl');
constdbg=gl&&gl.getExtension('WEBGL_debug_renderer_info');
constrenderer=dbg?gl.getParameter(dbg.UNMASKED_RENDERER_WEBGL):'n/a';
constvendor=dbg?gl.getParameter(dbg.UNMASKED_VENDOR_WEBGL):'n/a';
return{
ua:navigator.userAgent,
platform:navigator.platform,
canvas:canvasHash,
webglRenderer:renderer,
webglVendor:vendor,
timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,
language:navigator.language,
languages:(navigator.languages||[]).join(','),
screen:screen.width+'x'+screen.height,
colorDepth:screen.colorDepth,
dpr:window.devicePixelRatio,
cores:navigator.hardwareConcurrency,
memory:navigator.deviceMemory||'n/a',
};
}
"""
defstart_profile(pid):
"""启动配置,返回该配置的CDP调试端口"""
resp=requests.post(
BASE+"/api/v1/browser/start",
headers=HEADERS,
json={"profileId":pid},
timeout=30,
)
resp.raise_for_status()
returnresp.json()["data"]["debugPort"]
defcollect(port):
"""通过CDP连上去取指纹字段"""
withsync_playwright()asp:
browser=p.chromium.connect_over_cdp("http://127.0.0.1:%d"%port)
ctx=browser.contexts[0]
page=ctx.new_page()
page.goto("about:blank")
result=page.evaluate(COLLECT_JS)
browser.close()
returnresult
defrender_table(rows):
"""把采集结果渲染成等宽文本表格"""
keys=list(rows[0].keys())
width=max(len(k)forkinkeys)
header="|字段".ljust(width+6)+"|"+"|".join(
r["_name"].ljust(18)forrinrows
)+"|"
print(header)
print("-"*len(header))
forkinkeys:
ifk=="_name":
continue
line="|"+k.ljust(width+4)+"|"
line+="|".join(str(r[k])[:18].ljust(18)forrinrows)
print(line+"|")
defmain():
rows=[]
forpidinPROFILE_IDS:
port=start_profile(pid)
data=collect(port)
data["_name"]=pid
rows.append(data)
render_table(rows)
#关键字段唯一性检查:同一组环境之间不允许出现重复值
forfieldin["canvas","webglRenderer","screen","ua","timezone"]:
values=[r[field]forrinrows]
dup=len(values)!=len(set(values))
print("%-14s唯一性:%s"%(field,"存在重复,需检查"ifdupelse"通过"))
if__name__=="__main__":
main()
跑完看两点:一是表格里各环境的关键字段有没有撞车;二是脚本末尾那几行唯一性检查有没有通过。canvas或webglRenderer出现重复,说明噪声没生效或者环境配置被复制过;timezone和代理归属地不一致,回到4.2的表里对一遍。
示例C:本地MCP配置
MCP配置有两种常见形态,JSON用于通用AI客户端,TOML用于Windows下的Codex。端点统一是http://127.0.0.1:30898/mcp,通过mcp-remote桥接,请求头里带授权值。
JSON形态:
{
"mostlogin":{
"command":"npx",
"args":[
"-y",
"mcp-remote",
"http://127.0.0.1:30898/mcp",
"--transport",
"http-only",
"--allow-http",
"--header",
"Authorization:YOUR_MOSTLOGIN_TOKEN"
]
}
}
TOML形态(CodexonWindows):
[mcp_servers.mostlogin]
command="C:\\ProgramFiles\\nodejs\\npx.cmd"
args=[
"-y",
"mcp-remote",
"http://127.0.0.1:30898/mcp",
"--transport",
"http-only",
"--allow-http",
"--header",
"Authorization:YOUR_MOSTLOGIN_TOKEN"
]
startup_timeout_sec=30
tool_timeout_sec=60
Windows下有个必踩的坑:配置文件里command如果写npx,PowerShell会因为执行策略限制拉不起来进程,必须写成npx.cmd的完整路径,也就是上面TOML里的C:\\ProgramFiles\\nodejs\\npx.cmd。改完之后重启客户端让配置生效。
可用的自然语言指令示例:
· 列出MostLogin中可用的浏览器配置
· 启动名为TTSHOP-US-01的配置
· 打开编号1到10的配置,并访问卖家后台登录页
· 显示所有MostLoginMCP工具
两条安全提醒必须写在文档里:一是授权值等同密码,别出现在截图、公开文档、代码仓库和支持帖里;二是本地端点127.0.0.1只能被同一台电脑上的软件访问,网页版的远程AI应用通常连不上,不要为了让它连上就把端口暴露到公网。
另外说明一句,MCP与同步器目前主要面向浏览器环境,移动端实例不走这套。
六、验收与排错
6.1环境验收清单
新环境上线前,按下面六项过一遍,任意一项不过就别投产:
序号 |
验收项 |
方法 |
通过标准 |
1 |
指纹报告抽样比对 |
抽样环境访问指纹检测站点,导出报告 |
与台账记录一致,环境之间无重复 |
2 |
代理连通性 |
访问IP查询站点 |
出口IP与绑定记录一致 |
3 |
时区与IP归属地一致 |
对比页面读到的时区与IP库查询结果 |
两者对应,且符合夏令时规则 |
4 |
WebRTC泄漏 |
WebRTC检测页面查看ICE候选 |
无本地内网IP与真实公网IP |
5 |
DNS泄漏 |
DNS泄漏检测站点 |
解析服务器归属与出口IP一致 |
6 |
移动端实例检查 |
查看机型、运营商、传感器、GooglePlay |
机型真实、传感器有噪声、应用可正常下载 |
6.2常见故障排查表
症状 |
可能原因 |
处理 |
后台反复要求短信或邮箱验证 |
出口IP归属地与时区或语言不一致 |
核对并把三者统一 |
新店铺上线后很快受限 |
注册时段网络波动,或IP历史信誉差 |
换独享住宅IP,先做1到2周冷启动再放量 |
一个环境里登录了两个店铺 |
制度执行不到位 |
拆分环境,补登记并复查操作日志 |
检测站显示的IP与代理后台不一致 |
WebRTC泄漏 |
关闭WebRTC或强制走代理出口 |
检测站列出本地DNS服务器 |
DNS泄漏 |
开启DNS随代理,禁用本地回退 |
移动端App闪退或功能缺失 |
用了x86模拟器,或内核与App不匹配 |
换成真实Android实例 |
视频上传频繁中断 |
代理带宽不足或链路抖动 |
换线路,避开高峰时段上传 |
客服后台消息延迟明显 |
代理延迟高或节点距离远 |
测延迟后换就近节点 |
每次启动环境指纹字段都不一样 |
配置未保存,或开了随机模式 |
固定参数,关闭随机指纹 |
团队成员误操作他人店铺 |
权限分配过宽 |
收紧到店铺负责人粒度 |
两个环境的Canvas哈希相同 |
噪声未生效,或环境由复制产生 |
重新生成指纹,禁止复制用户数据目录 |
云手机无法安装海外应用 |
GooglePlay服务未就绪或区域限制 |
检查账号区域与机型匹配,改用APK直接安装 |
当下,移动优先平台正在把检测重心往App端搬,这是这两年变化很明显的一条线。网页端指纹那套东西已经被研究得很透了,参数自洽性怎么校验、源码层改写和JS注入的差别在哪,行业里基本形成共识。但App端完全不是一回事:IMEI、MAC、基带版本、运营商信息、传感器噪声、电池曲线,这些维度网页端一个都拿不到,而它们恰恰是区分真实设备与虚拟环境的高价值信号。所以移动端场景用真实Android实例而不是模拟器,这件事的必要性只会上升不会下降。
此外,AI行为建模日益普及。平台侧在分析什么?鼠标轨迹的形状、表单输入的节奏、页面打开的顺序、会话时长分布、操作间隔的统计特征。这些是行为层的东西,单纯靠改参数解决不了。工具侧的应对也在往这个方向走,行为随机化、自然交互模拟、输入延迟注入,像同步器里给按键和点击加50到100毫秒随机延迟这类设计,本质上就是在处理行为层的自然度。未来的多店铺环境管理,会从"改参数"走向"整条设备身份链路的自洽,加上行为曲线的自然"。
监管和平台规则也在演变。往乐观的方向走,如果平台建立起"认证企业身份可经营多店面"的机制,合规多店铺的路径会更清晰,卖家不用再靠技术堆叠去证明自己的独立性;往保守的方向走,如果判定标准持续趋严,纯技术堆砌的边际收益会一直下降,投入产出比越来越难看。
技术环境解决的问题是"看得见的同一性",它能把设备身份、网络出口、存储痕迹这些维度拆开,但它变不出一个真实的独立经营主体,也变不出差异化的商品和服务。长期安全性取决于主体是不是真的独立、商品和服务是不是真的做得住。把环境管理纳入日常SOP,按周按月巡检,出问题能追溯、能定位,而不是等店铺受限了再回头补。工具是基础设施,怎么用、用在什么前提上,才是决定结果的东西。