ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

wxid批量添加实战:从手动搜不到到Hook接口打通

2026/10/6 9:44:02 拓冰建站 浏览量
wxid批量添加实战:从手动搜不到到Hook接口打通 简介这是一套围绕微信‘wxid_’前缀账号添加难题的代码资源包适用于普通用户、社群运营者以及从事微信辅助工具开发的技术人员。由于这类微信号由系统自动分配常规搜索无法直达资源以HTML代码结合inscode配置为主要手段演示了安卓端发送特定格式HTML来唤起添加请求的路径并提示了易错点如代码空格处理。同时还涵盖借助共同好友、微信群成员列表、扫描个人二维码等替代添加方式也适用于自定义微信号受限场景。压缩包共3个文件包含HTML页面、inscode代码片段及gitignore配置文件整体大小仅5KB结构简洁、便于直接查看或部署。已有1305人学习/下载可快速获取可运行的添加脚本、操作要点与隐私保护提醒适合作为轻量工具参考或快速验证思路。1. wxid 微信号添加方法从手动搜不到到接口能打通的最短路径做微信客服、好友管理和批量回访的人十有八九都碰过同一个问题拿到一堆以wxid_开头的原始微信号手动去微信里搜不是提示“用户不存在”就是“无法添加”。这不是数据错了而是走错了入口。wxid是微信注册时生成的内部标识客户端对非好友默认屏蔽了这条搜索入口但 Windows 客户端注入层仍然留着一个可用的添加接口。这份代码包做的就是把这个黑匣子拆开再封装好你传入wxid、验证语和添加场景脚本按可控节奏把请求发出去再把回执整理成可读日志。适合做客户触达、老客回访和账号测试的开发者也适合被海量脏数据逼到想写脚本的运营。2. 先把 wxid 的边界理清楚格式差异、方案选型与运行环境2.1 wxid 和微信号差在哪拿到一条数据先做预判很多刚接触这批数据的人会把wxid和“微信号”当成一回事。实际上微信账号体系里有好几套标识最常见的四种是原始wxid、自定义微信号、群聊内部标识以及开放平台里的openid。wxid是注册时随机生成的原始标识形如wxid_a1b2c3d4e5f6一旦生成基本终身不变。自定义微信号则是用户自己在“设置-微信号”里改过的名字可以是abc123、zhangsan_2024这种任意组合。区别在于自定义微信号是对外搜索的入口而wxid在客户端里对非好友是藏起来的。换句话说手动搜不到不代表数据库里没有只是这个字段本就不是设计给手动搜索用的。数据类型常见形态能否直接用于添加原始 wxidwxid_a1b2c3d4e5f6能但必须走注入层接口自定义微信号zhangsan_2024能但搜索结果受对方设置限制群聊内部标识可能是 wxid_ 或 gh_ 开头需要先解析不能直接当 wxid 用openid / unionido6_xABCDEF 格式不能另一套开放平台编号体系从 Excel 或者客服系统导出来的数据通常是一个单元格里混着昵称、备注、手机号和wxid看起来像这样张三 138xxxx wxid_a1b2...。如果你直接把整段字符串塞进添加接口微信内部是认不出来的。必须先做一次提取只把wxid_后面那串字符捞出来。另外还要提醒一个细节wxid_后面的字符长度不是固定的短的可能 6 位长的能到 32 位正则可以放宽到{4,64}。有些导出工具会把字符串截断成wxid_a1b2就换行这种残缺数据即使发出去也不会被微信识别应该在清洗阶段直接过滤掉。2.2 为什么选 Hook 注入而不是协议脚本市面上做微信二次开发大致有三个方向。第一类是模拟网页协议登录这种方案在早期流行但随着微信接口收紧大批协议脚本已经失效而且需要维护复杂的加解密算法拿到回执也不稳定不建议作为生产方案。第二类是 RPA 纯按键操作稳是稳但它把“输入-点击-确认-等待”全走一遍单条耗时太长窗口一被遮挡还容易误点不适合批量场景。这份代码包用的是第三类Windows 客户端 Hook 注入。思路是把一个注入 DLL 挂到本机已经登录好的微信进程里通过它去调用微信内部封装好的添加函数。比协议脚本更稳的地方在于它复用你本机微信的真实登录态不需要额外的密钥和扫码授权比 RPA 快的地方在于走的是内存接口而不是模拟点击单条请求从发出到拿到回执通常在秒级完成。我不建议一上来就追求“全自动无人值守”。这个方案再稳也架不住人类当天心情不好把微信窗口拖到第二屏去。我一般会把调度脚本和管理界面分开跑注入 DLL 负责和微信进程通信调度脚本负责排队、重试、写日志。这样即使注入端崩了调度脚本里的队列不会丢重启注入端后还能续跑。2.3 环境准备与启动顺序三分钟先跑通最小链路在跑批量之前先把运行环境核对一遍。这个方案对系统要求并不高但有几个前置条件比较死板缺一个都会在启动阶段卡住依赖项建议配置说明操作系统Windows 10 / 11 64 位Hook 方案不跨平台微信版本PC 微信 3.9 系列需要匹配注入 DLL 的符号偏移Python3.8 及以上用到了 f-string 和类型标注注入器代码包内自带以管理员身份运行网络正常外网即可与公网服务器无强依赖建议启动顺序是先开注入器再开 Python 调度端。如果你先把正常微信登录了注入器再挂载 DLL大概率会因为进程已被占用而注入失败。这个顺序问题我在后文避坑部分还会单独讲。# 第一步结束已经启动的微信进程确保一个干净的注入环境 taskkill /IM WeChat.exe /F # 第二步以管理员身份启动注入器把 DLL 挂到新启动的微信进程上 injector.exe --wechat C:\Program Files\Tencent\WeChat\WeChat.exe --pipe wxrpc_7001 # 第三步启动 Python 调度端连接同名管道 python main.py --pipe wxrpc_7001 --scene 3 --interval 8这里--pipe是注入 DLL 与调度脚本之间通信的管道名两边必须严格一致。--scene表示添加好友的场景来源3代表搜索添加4代表群聊添加6代表名片推荐不同场景在风控上的权重不同。--interval是两条添加请求之间的间隔秒数批量场景建议不低于 8 秒。跑完这三步如果看到类似pipe connected的日志说明最小链路已经通了。接下来就可以进入核心请求封装环节了。3. 核心添加流程怎么走通请求封装、回执解析与频控参数3.1 把“添加好友”翻译成一段 JSON注入 DLL 挂在微信进程里但它并不知道你想干什么需要调度脚本把“添加某个 wxid”翻译成一个结构化的请求体发给它。我习惯用 JSON 作为传输格式字段简单出了问题也好排查。# handler.py —— 构造添加好友请求体 import json def build_add_request(wxid: str, verify_msg: str, scene: int 3) - dict: 生成一条添加好友请求。 verify_msg 会被截断到 30 字以内避免触发微信的文本长度校验。 return { cmd: add_friend, wxid: wxid.strip(), verify: verify_msg[:30], scene: scene, # 3搜索添加, 4群聊添加, 6名片添加 timeout: 8, # 等待回执的超时秒数 }cmd字段是给注入 DLL 做路由用的它收到add_friend后会去调用微信内部对应的添加函数。wxid必须是干净的一串字符任何多余空格、换行、不可见字符都会导致微信内部解析失败。scene的取值直接决定请求走哪条业务路径这个参数没有好坏之分但它会显著影响触达成功率后面我会单独展开。timeout是调度端等待回执的最长时间如果超过 8 秒还没有回话这次调用应该被标记为超时而不是成功。请求体构造完后还需要一个负责和注入 DLL 通信的客户端类。真实实现中Windows 下一般走命名管道或本地 TCP 回环地址这里给出接口骨架# handler.py 续 —— RPC 客户端封装 class WechatRpcClient: 与注入 DLL 建立连接发送请求并接收回执。 def __init__(self, pipe: str wxrpc_7001): self.pipe pipe self.rpc_id 0 def call(self, payload: dict) - tuple[bool, int]: # 真实环境里这里通过管道发送 payload并同步等待 DLL 返回 # 返回格式固定为 (是否成功, 错误码) self.rpc_id 1 try: raw json.dumps(payload, ensure_asciiFalse).encode(utf-8) reply self._send(raw) return reply.get(ok, False), reply.get(code, -1) except Exception: return False, -1 def _send(self, raw: bytes) - dict: # 此处省略管道读写细节按你本机注入 DLL 的协议对接即可 # 连接目标通常是 \\.\pipe\wxrpc_7001 raise NotImplementedError这个骨架里我故意把_send留空因为不同注入 DLL 的管道协议略有差异但外层这套“构造请求-发送-取回执”的模式是通用的。你在自己项目里接入时只需要把_send替换成实际管道读写代码其余逻辑不用动。3.2 发送循环间隔、重试与失败回退请求封装好了接下来是核心的批量发送逻辑。这里的关键不是“能发出去”而是“发得稳”。我见过太多人写了一个 for 循环就上线结果跑到第 5 条就被微信风控掐断整批数据全部作废。# sender.py —— 带重试和频控的批量发送逻辑 import csv import time from handler import build_add_request, WechatRpcClient def run_add_batch(pipe_name: str, wxid_list: list[str], verify_msg: str, scene: int 3, interval: int 8) - list[tuple]: client WechatRpcClient(pipe_name) rows [] for raw in wxid_list: wxid raw.strip() if not wxid.startswith(wxid_): rows.append((wxid, skip, 格式不符合)) continue ok, code client.call(build_add_request(wxid, verify_msg, scene)) if ok and code 0: rows.append((wxid, sent, 0)) else: # 1205 / 1202 都是风控短时拦截等待时间翻倍后再试一次 wait interval * 2 if code in (1205, 1202) else interval time.sleep(wait) ok2, code2 client.call(build_add_request(wxid, verify_msg, scene)) rows.append((wxid, retry_sent if ok2 and code2 0 else failed, code2)) # 单条间隔由这里控制不要随意改小 time.sleep(interval) with open(add_result.csv, w, newline, encodingutf-8-sig) as fp: writer csv.writer(fp) writer.writerow([wxid, 状态, 错误码]) writer.writerows(rows) return rows这段代码做了三件比较重要的事。第一对格式不符合的wxid直接跳过而不是硬发给接口制造错误回执第二遇到 1205、1202 这类风控拦截码时把等待时间翻倍再重试一次给风控留出冷却窗口第三每处理完一条强制睡interval秒这是批量方案能不能长时间运行的分水岭。你可能会问我为什么不做三次重试我的习惯是单个账号最多重试一次。如果一次重试还是失败说明这条数据本身就有问题或者账号已经进入短时观察期再试只会增加风险。3.3 频控参数选多大才不触发风控频控参数是整个方案里最像玄学的部分。微信没有官方文档告诉你“每分钟最多加几个”这些数值都是测试账号拿真金白银试出来的经验值。我整理了一张参考表按稳妥程度排列场景单条间隔单批数量批次间隔备注全部搜索添加15 秒20 条10 分钟最稳妥推荐首跑混合场景添加10 秒30 条5 分钟有存量好友基础再用群聊场景添加8 秒50 条3 分钟权重略低于搜索但也别贪这个表不是让你死记硬背而是当成初始值。先跑一批测试数据观察回执里有没有出现 1205、1202 这类拦截码有就把间隔往上加。账号有实名、有绑卡、有历史聊天记录的通常能扛得住更快的节奏新注册的纯测试号间隔要更保守一些。还有一条经验不要在一天里的固定时间点集中跑完所有数据。微信的风控系统对“每天同一时刻批量动作”的敏感度很高我一般会把 100 条数据拆成上午 30 条、下午 30 条、晚上 40 条分别在不同的时段执行。4. 批量客户数据清洗wxid 提取、去重与白名单机制4.1 从 Excel 和群聊记录里把 wxid 抠出来拿到生产数据后第一步不是添加而是清洗。从客服系统导出的客户表wxid往往混在备注、来源和标签里直接拿去跑批量会把大量无效请求发给接口。# cleaner.py —— 从脏文本中提取 wxid import re import hashlib from collections import OrderedDict def extract_wxid(raw: str) - str: 从混合文本中提取形如 wxid_xxx 的原始微信号。 处理三种典型脏数据 1. 文本中有昵称、手机号、wxid 混杂 2. 单元格以 微信号 开头 3. 导出工具把 wxid_ 和后面字符拆到了两列 if not raw: return raw raw.replace(\u00a0, ).strip() # 最标准的情况直接匹配 wxid_ 开头的连续字符 m re.search(r(wxid_[A-Za-z0-9_]{4,64}), raw) if m: return m.group(1) # 兼容 微信号 wxid_a1b2 这种带中文冒号的写法 m2 re.search(rwxid_?\s*([A-Za-z0-9_]{4,64}), raw) if m2: return wxid_ m2.group(1) return 这里有两个细节值得注意。第一个是\u00a0这是 Excel 里常见的不同断空格肉眼看不出来但会让正则匹配失败所以清洗时先替换掉。第二个是第二段正则我故意把wxid_和一个或多个空白字符分开处理用来兼容那些“wxid_在单元格上一行、后面字符在下一行”的导出文件。4.2 去重不能当成普通字符串处理很多人在去重上吃过亏直接把wxid放进 Python 的set里看似去掉了重复项但漏掉了那些因为清洗不彻底而带有多余空格的同一条数据。def dedup_wxids(items: list[str]) - list[str]: 先提取再哈希去重保留第一次出现的顺序。 不使用 set 直接去重是因为脏数据里同一个 wxid 可能带不同空白符或全角符号提取后再哈希才是真正的唯一键。 seen set() result [] for raw in items: wxid extract_wxid(raw) if not wxid: continue key hashlib.md5(wxid.encode(utf-8)).hexdigest() if key not in seen: seen.add(key) result.append(wxid) return result我之所以先做哈希再做去重是因为原始数据里同一个wxid可能会出现“wxid_a1b2”“wxid_a1b2”两种形态直接把原始字符串丢进set会当成两条数据最后还是会给同一个账号发两次请求。提取之后再做哈希就把这类问题挡在源头了。另外wxid的字符集是字母、数字、下划线的组合理论上不存在大小写变体但如果你的数据源里有全角字符正则匹配不到会直接返回空字符串这种情况需要回到上一节用extract_wxid先过一遍。4.3 白名单、验证语模板与分发队列清洗完的数据不能一股脑全发出去。生产环境里总有一些客户明确表示过“不需要被打扰”或者已经在好友列表里。这类账号应该从批量队列里抽出来单独维护一个白名单文件。白名单文件whitelist.csv我习惯用两列结构字段含义wxid需要跳过的原始标识reason跳过原因比如“已是好友”“客户投诉过”在调度脚本里加上一个过滤函数读取白名单后在发送前直接跳过匹配项。这个动作看似多余但能避免最尴尬的翻车你费尽心思写好了代码结果把已经通过好友验证的老客户又加了一遍。验证语模板也要注意。微信对重复文本的识别很敏感如果 100 条请求都用一模一样的“你好我是某某”命中风控的概率会明显上升。我一般会准备三到五个模板按不同的来源场景轮换使用。比如从微信群来的用“群内看到您的名片”从历史订单来的用“关于您上次咨询的问题想跟您同步一下”。让每条验证语都带有具体上下文不只是为了触达率更是为了让接口回执更真实。5. 避坑排查四个经典翻车场景与现场定位手段5.1 “添加成功”回执到了对方却没收到申请现象代码返回code0日志也标记了sent但测试对端手机屏幕上根本没有出现好友申请。原因这个回执只代表“调用链路上没有出错”并不代表微信后台真的把请求下发给了对方。常见诱因有两个。第一是wxid本身已经从微信数据库里被回收或冻结接口返回假成功第二是scene传了群聊添加值但请求并没有从真实群聊上下文发出微信内部直接丢弃了请求。解决先在可控小号上做双向验证小号 A 添加小号 B确认 B 真的收到申请后再跑正式数据。如果单条测试能收到、批量测试收不到那就是节奏问题回到上一章的频控参数表重新设间隔。5.2 加到第 5 个号微信直接掉线现象批量脚本运行到第 4、5 条时微信主界面突然闪断重新打开后提示需要重新登录甚至出现短时限制登录警告。原因这是最典型的批量触达风控短时间内好友请求数量超过微信侧阈值。某次测试里我把间隔调到 5 秒第 5 条就触发了限制而把间隔拉长到 15 秒后同一批数据没有任何异常。解决把单条间隔提到 15 秒单批数量压到 20 条以内两批之间停 10 分钟。如果账号本身没有实名或绑卡还需要在这个基础上再保守一倍。这个参数没有商量余地宁慢勿快。5.3 脚本报“pipe not found”或“connect fail”现象启动调度脚本后立刻报pipe not found注入端日志显示没有任何连接进入。原因微信进程已经在注入器之前启动了DLL 无法挂载到已加载的进程上或者管道名在注入器和调度脚本两边不一致。Windows 下命名管道的连接失败九成是这两个原因。解决先taskkill /IM WeChat.exe /F把微信进程彻底结束再以管理员身份运行注入器等它输出“inject success”后再启动 Python 调度端。同时核对两边的--pipe参数字符串大小写和末尾数字都要完全一致。5.4 接口没有报错但添加按钮一直是灰色现象某些wxid传入后注入层成功返回但微信界面里对应搜索结果显示的是灰色不可点按钮。原因对方的隐私设置关闭了“通过搜索添加”或者该账号当前处于风险状态微信不允许通过任何接口触达。这类账号在接口层面没有明确错误码属于数据本身不可用。解决把这批wxid从正式队列里摘出来单独放进一个“不可用名单”不要再重试。反复重试不会提高成功率反而会让整个账号的权重被拉低。5.5 代码改完重启日志没有任何输出现象修改了验证语模板后重新启动调度脚本终端窗口干干净净既没有错误也没有正常日志。原因Python 的 stdout 在 Windows 下默认有缓冲加上程序跑了几分钟后才打印日志全被吞在缓冲区里另一个常见原因是脚本里用了print但没加flushTrue进程异常退出时内容还没来得及落盘。解决启动命令里加PYTHONUNBUFFERED1或者把日志统一写进文件而不是终端。我在代码包里默认就是写两路日志一份终端实时输出一份runtime.log落盘这样即使终端关掉了后续也能靠文件排查问题。6. 把添加结果变成可回查的账单回调校验与定时巡检6.1 真实成功的判定双确认机制发送回执为 0只能说明请求被微信接收不能说明对方已经看到并处理。想要知道真实触达结果需要第二层数据微信收到“朋友验证通知”后产生的事件回调以及对方通过好友请求后触发的好友列表变动。我把这个逻辑叫双确认。第一确认是发送回执来自请求接口本身第二确认是事件回调来自微信内部的消息推送。两段日志对得上才算一条真实成功记录。具体做法是在调度端保留一张sent记录表回调解析器收到friend_add_event时把对应的wxid标记为“已接收”。# 把事件回调单独挂一个监听进程不跟发送进程混在一起 python monitor.py --pipe wxrpc_7001 --event friend_add --db result.sqlite这样回调解析和发送调度互相独立即使发送进程崩了回调进程也能持续积累数据下次重启后去重补发就行。6.2 定时巡检与红黄牌机制批量添加不是一次性脚本它需要持续跑所以要给队列加一道巡检机制。我把每天的运行时段拆成上午、下午、晚上三段每段结束后对result.sqlite做一次统计新增了多少条白名单命中、多少条超时未回执、多少条被风控拦截。对于超过 120 秒还没有任何回执的请求标记为黄牌同一条数据连续黄牌两次就升级为红牌直接踢出队列。这个机制解决的是“脚本卡死但进程还活着”的尴尬场面——没有它你可能过了半天才发现某批数据全部阻塞在管道读写上。从那以后我每次换微信版本或者改scene参数都强制在小号上跑一遍三个检查发送回执为 0、对方真实收到申请、通过后回调入库。三道都绿了才轮到正式数据进队列。这套流程看着慢但省下的全是踩坑的时间希望帮到你。本文还有配套的精品资源点击获取