:從手動搜不到到Hook接口打通)
簡介這是一套圍繞微信‘wxid_’前綴賬號添加難題的代碼資源包適用于普通用戶、社群運營者以及從事微信輔助工具開發(fā)的技術人員。由于這類微信號由系統(tǒng)自動分配常規(guī)搜索無法直達資源以HTML代碼結合inscode配置為主要手段演示了安卓端發(fā)送特定格式HTML來喚起添加請求的路徑并提示了易錯點如代碼空格處理。同時還涵蓋借助共同好友、微信群成員列表、掃描個人二維碼等替代添加方式也適用于自定義微信號受限場景。壓縮包共3個文件包含HTML頁面、inscode代碼片段及gitignore配置文件整體大小僅5KB結構簡潔、便于直接查看或部署。已有1305人學習/下載可快速獲取可運行的添加腳本、操作要點與隱私保護提醒適合作為輕量工具參考或快速驗證思路。1. wxid 微信號添加方法從手動搜不到到接口能打通的最短路徑做微信客服、好友管理和批量回訪的人十有八九都碰過同一個問題拿到一堆以wxid_開頭的原始微信號手動去微信里搜不是提示“用戶不存在”就是“無法添加”。這不是數(shù)據(jù)錯了而是走錯了入口。wxid是微信注冊時生成的內部標識客戶端對非好友默認屏蔽了這條搜索入口但 Windows 客戶端注入層仍然留著一個可用的添加接口。這份代碼包做的就是把這個黑匣子拆開再封裝好你傳入wxid、驗證語和添加場景腳本按可控節(jié)奏把請求發(fā)出去再把回執(zhí)整理成可讀日志。適合做客戶觸達、老客回訪和賬號測試的開發(fā)者也適合被海量臟數(shù)據(jù)逼到想寫腳本的運營。2. 先把 wxid 的邊界理清楚格式差異、方案選型與運行環(huán)境2.1 wxid 和微信號差在哪拿到一條數(shù)據(jù)先做預判很多剛接觸這批數(shù)據(jù)的人會把wxid和“微信號”當成一回事。實際上微信賬號體系里有好幾套標識最常見的四種是原始wxid、自定義微信號、群聊內部標識以及開放平臺里的openid。wxid是注冊時隨機生成的原始標識形如wxid_a1b2c3d4e5f6一旦生成基本終身不變。自定義微信號則是用戶自己在“設置-微信號”里改過的名字可以是abc123、zhangsan_2024這種任意組合。區(qū)別在于自定義微信號是對外搜索的入口而wxid在客戶端里對非好友是藏起來的。換句話說手動搜不到不代表數(shù)據(jù)庫里沒有只是這個字段本就不是設計給手動搜索用的。數(shù)據(jù)類型常見形態(tài)能否直接用于添加原始 wxidwxid_a1b2c3d4e5f6能但必須走注入層接口自定義微信號zhangsan_2024能但搜索結果受對方設置限制群聊內部標識可能是 wxid_ 或 gh_ 開頭需要先解析不能直接當 wxid 用openid / unionido6_xABCDEF 格式不能另一套開放平臺編號體系從 Excel 或者客服系統(tǒng)導出來的數(shù)據(jù)通常是一個單元格里混著昵稱、備注、手機號和wxid看起來像這樣張三 138xxxx wxid_a1b2...。如果你直接把整段字符串塞進添加接口微信內部是認不出來的。必須先做一次提取只把wxid_后面那串字符撈出來。另外還要提醒一個細節(jié)wxid_后面的字符長度不是固定的短的可能 6 位長的能到 32 位正則可以放寬到{4,64}。有些導出工具會把字符串截斷成wxid_a1b2就換行這種殘缺數(shù)據(jù)即使發(fā)出去也不會被微信識別應該在清洗階段直接過濾掉。2.2 為什么選 Hook 注入而不是協(xié)議腳本市面上做微信二次開發(fā)大致有三個方向。第一類是模擬網(wǎng)頁協(xié)議登錄這種方案在早期流行但隨著微信接口收緊大批協(xié)議腳本已經失效而且需要維護復雜的加解密算法拿到回執(zhí)也不穩(wěn)定不建議作為生產方案。第二類是 RPA 純按鍵操作穩(wěn)是穩(wěn)但它把“輸入-點擊-確認-等待”全走一遍單條耗時太長窗口一被遮擋還容易誤點不適合批量場景。這份代碼包用的是第三類Windows 客戶端 Hook 注入。思路是把一個注入 DLL 掛到本機已經登錄好的微信進程里通過它去調用微信內部封裝好的添加函數(shù)。比協(xié)議腳本更穩(wěn)的地方在于它復用你本機微信的真實登錄態(tài)不需要額外的密鑰和掃碼授權比 RPA 快的地方在于走的是內存接口而不是模擬點擊單條請求從發(fā)出到拿到回執(zhí)通常在秒級完成。我不建議一上來就追求“全自動無人值守”。這個方案再穩(wěn)也架不住人類當天心情不好把微信窗口拖到第二屏去。我一般會把調度腳本和管理界面分開跑注入 DLL 負責和微信進程通信調度腳本負責排隊、重試、寫日志。這樣即使注入端崩了調度腳本里的隊列不會丟重啟注入端后還能續(xù)跑。2.3 環(huán)境準備與啟動順序三分鐘先跑通最小鏈路在跑批量之前先把運行環(huán)境核對一遍。這個方案對系統(tǒng)要求并不高但有幾個前置條件比較死板缺一個都會在啟動階段卡住依賴項建議配置說明操作系統(tǒng)Windows 10 / 11 64 位Hook 方案不跨平臺微信版本PC 微信 3.9 系列需要匹配注入 DLL 的符號偏移Python3.8 及以上用到了 f-string 和類型標注注入器代碼包內自帶以管理員身份運行網(wǎng)絡正常外網(wǎng)即可與公網(wǎng)服務器無強依賴建議啟動順序是先開注入器再開 Python 調度端。如果你先把正常微信登錄了注入器再掛載 DLL大概率會因為進程已被占用而注入失敗。這個順序問題我在后文避坑部分還會單獨講。# 第一步結束已經啟動的微信進程確保一個干凈的注入環(huán)境 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是兩條添加請求之間的間隔秒數(shù)批量場景建議不低于 8 秒。跑完這三步如果看到類似pipe connected的日志說明最小鏈路已經通了。接下來就可以進入核心請求封裝環(huán)節(jié)了。3. 核心添加流程怎么走通請求封裝、回執(zhí)解析與頻控參數(shù)3.1 把“添加好友”翻譯成一段 JSON注入 DLL 掛在微信進程里但它并不知道你想干什么需要調度腳本把“添加某個 wxid”翻譯成一個結構化的請求體發(fā)給它。我習慣用 JSON 作為傳輸格式字段簡單出了問題也好排查。# handler.py —— 構造添加好友請求體 import json def build_add_request(wxid: str, verify_msg: str, scene: int 3) - dict: 生成一條添加好友請求。 verify_msg 會被截斷到 30 字以內避免觸發(fā)微信的文本長度校驗。 return { cmd: add_friend, wxid: wxid.strip(), verify: verify_msg[:30], scene: scene, # 3搜索添加, 4群聊添加, 6名片添加 timeout: 8, # 等待回執(zhí)的超時秒數(shù) }cmd字段是給注入 DLL 做路由用的它收到add_friend后會去調用微信內部對應的添加函數(shù)。wxid必須是干凈的一串字符任何多余空格、換行、不可見字符都會導致微信內部解析失敗。scene的取值直接決定請求走哪條業(yè)務路徑這個參數(shù)沒有好壞之分但它會顯著影響觸達成功率后面我會單獨展開。timeout是調度端等待回執(zhí)的最長時間如果超過 8 秒還沒有回話這次調用應該被標記為超時而不是成功。請求體構造完后還需要一個負責和注入 DLL 通信的客戶端類。真實實現(xiàn)中Windows 下一般走命名管道或本地 TCP 回環(huán)地址這里給出接口骨架# handler.py 續(xù) —— RPC 客戶端封裝 class WechatRpcClient: 與注入 DLL 建立連接發(fā)送請求并接收回執(zhí)。 def __init__(self, pipe: str wxrpc_7001): self.pipe pipe self.rpc_id 0 def call(self, payload: dict) - tuple[bool, int]: # 真實環(huán)境里這里通過管道發(fā)送 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: # 此處省略管道讀寫細節(jié)按你本機注入 DLL 的協(xié)議對接即可 # 連接目標通常是 \\.\pipe\wxrpc_7001 raise NotImplementedError這個骨架里我故意把_send留空因為不同注入 DLL 的管道協(xié)議略有差異但外層這套“構造請求-發(fā)送-取回執(zhí)”的模式是通用的。你在自己項目里接入時只需要把_send替換成實際管道讀寫代碼其余邏輯不用動。3.2 發(fā)送循環(huán)間隔、重試與失敗回退請求封裝好了接下來是核心的批量發(fā)送邏輯。這里的關鍵不是“能發(fā)出去”而是“發(fā)得穩(wěn)”。我見過太多人寫了一個 for 循環(huán)就上線結果跑到第 5 條就被微信風控掐斷整批數(shù)據(jù)全部作廢。# sender.py —— 帶重試和頻控的批量發(fā)送邏輯 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, 狀態(tài), 錯誤碼]) writer.writerows(rows) return rows這段代碼做了三件比較重要的事。第一對格式不符合的wxid直接跳過而不是硬發(fā)給接口制造錯誤回執(zhí)第二遇到 1205、1202 這類風控攔截碼時把等待時間翻倍再重試一次給風控留出冷卻窗口第三每處理完一條強制睡interval秒這是批量方案能不能長時間運行的分水嶺。你可能會問我為什么不做三次重試我的習慣是單個賬號最多重試一次。如果一次重試還是失敗說明這條數(shù)據(jù)本身就有問題或者賬號已經進入短時觀察期再試只會增加風險。3.3 頻控參數(shù)選多大才不觸發(fā)風控頻控參數(shù)是整個方案里最像玄學的部分。微信沒有官方文檔告訴你“每分鐘最多加幾個”這些數(shù)值都是測試賬號拿真金白銀試出來的經驗值。我整理了一張參考表按穩(wěn)妥程度排列場景單條間隔單批數(shù)量批次間隔備注全部搜索添加15 秒20 條10 分鐘最穩(wěn)妥推薦首跑混合場景添加10 秒30 條5 分鐘有存量好友基礎再用群聊場景添加8 秒50 條3 分鐘權重略低于搜索但也別貪這個表不是讓你死記硬背而是當成初始值。先跑一批測試數(shù)據(jù)觀察回執(zhí)里有沒有出現(xiàn) 1205、1202 這類攔截碼有就把間隔往上加。賬號有實名、有綁卡、有歷史聊天記錄的通常能扛得住更快的節(jié)奏新注冊的純測試號間隔要更保守一些。還有一條經驗不要在一天里的固定時間點集中跑完所有數(shù)據(jù)。微信的風控系統(tǒng)對“每天同一時刻批量動作”的敏感度很高我一般會把 100 條數(shù)據(jù)拆成上午 30 條、下午 30 條、晚上 40 條分別在不同的時段執(zhí)行。4. 批量客戶數(shù)據(jù)清洗wxid 提取、去重與白名單機制4.1 從 Excel 和群聊記錄里把 wxid 摳出來拿到生產數(shù)據(jù)后第一步不是添加而是清洗。從客服系統(tǒng)導出的客戶表wxid往往混在備注、來源和標簽里直接拿去跑批量會把大量無效請求發(fā)給接口。# cleaner.py —— 從臟文本中提取 wxid import re import hashlib from collections import OrderedDict def extract_wxid(raw: str) - str: 從混合文本中提取形如 wxid_xxx 的原始微信號。 處理三種典型臟數(shù)據(jù) 1. 文本中有昵稱、手機號、wxid 混雜 2. 單元格以 微信號 開頭 3. 導出工具把 wxid_ 和后面字符拆到了兩列 if not raw: return raw raw.replace(\u00a0, ).strip() # 最標準的情況直接匹配 wxid_ 開頭的連續(xù)字符 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 這里有兩個細節(jié)值得注意。第一個是\u00a0這是 Excel 里常見的不同斷空格肉眼看不出來但會讓正則匹配失敗所以清洗時先替換掉。第二個是第二段正則我故意把wxid_和一個或多個空白字符分開處理用來兼容那些“wxid_在單元格上一行、后面字符在下一行”的導出文件。4.2 去重不能當成普通字符串處理很多人在去重上吃過虧直接把wxid放進 Python 的set里看似去掉了重復項但漏掉了那些因為清洗不徹底而帶有多余空格的同一條數(shù)據(jù)。def dedup_wxids(items: list[str]) - list[str]: 先提取再哈希去重保留第一次出現(xiàn)的順序。 不使用 set 直接去重是因為臟數(shù)據(jù)里同一個 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我之所以先做哈希再做去重是因為原始數(shù)據(jù)里同一個wxid可能會出現(xiàn)“wxid_a1b2”“wxid_a1b2”兩種形態(tài)直接把原始字符串丟進set會當成兩條數(shù)據(jù)最后還是會給同一個賬號發(fā)兩次請求。提取之后再做哈希就把這類問題擋在源頭了。另外wxid的字符集是字母、數(shù)字、下劃線的組合理論上不存在大小寫變體但如果你的數(shù)據(jù)源里有全角字符正則匹配不到會直接返回空字符串這種情況需要回到上一節(jié)用extract_wxid先過一遍。4.3 白名單、驗證語模板與分發(fā)隊列清洗完的數(shù)據(jù)不能一股腦全發(fā)出去。生產環(huán)境里總有一些客戶明確表示過“不需要被打擾”或者已經在好友列表里。這類賬號應該從批量隊列里抽出來單獨維護一個白名單文件。白名單文件whitelist.csv我習慣用兩列結構字段含義wxid需要跳過的原始標識reason跳過原因比如“已是好友”“客戶投訴過”在調度腳本里加上一個過濾函數(shù)讀取白名單后在發(fā)送前直接跳過匹配項。這個動作看似多余但能避免最尷尬的翻車你費盡心思寫好了代碼結果把已經通過好友驗證的老客戶又加了一遍。驗證語模板也要注意。微信對重復文本的識別很敏感如果 100 條請求都用一模一樣的“你好我是某某”命中風控的概率會明顯上升。我一般會準備三到五個模板按不同的來源場景輪換使用。比如從微信群來的用“群內看到您的名片”從歷史訂單來的用“關于您上次咨詢的問題想跟您同步一下”。讓每條驗證語都帶有具體上下文不只是為了觸達率更是為了讓接口回執(zhí)更真實。5. 避坑排查四個經典翻車場景與現(xiàn)場定位手段5.1 “添加成功”回執(zhí)到了對方卻沒收到申請現(xiàn)象代碼返回code0日志也標記了sent但測試對端手機屏幕上根本沒有出現(xiàn)好友申請。原因這個回執(zhí)只代表“調用鏈路上沒有出錯”并不代表微信后臺真的把請求下發(fā)給了對方。常見誘因有兩個。第一是wxid本身已經從微信數(shù)據(jù)庫里被回收或凍結接口返回假成功第二是scene傳了群聊添加值但請求并沒有從真實群聊上下文發(fā)出微信內部直接丟棄了請求。解決先在可控小號上做雙向驗證小號 A 添加小號 B確認 B 真的收到申請后再跑正式數(shù)據(jù)。如果單條測試能收到、批量測試收不到那就是節(jié)奏問題回到上一章的頻控參數(shù)表重新設間隔。5.2 加到第 5 個號微信直接掉線現(xiàn)象批量腳本運行到第 4、5 條時微信主界面突然閃斷重新打開后提示需要重新登錄甚至出現(xiàn)短時限制登錄警告。原因這是最典型的批量觸達風控短時間內好友請求數(shù)量超過微信側閾值。某次測試里我把間隔調到 5 秒第 5 條就觸發(fā)了限制而把間隔拉長到 15 秒后同一批數(shù)據(jù)沒有任何異常。解決把單條間隔提到 15 秒單批數(shù)量壓到 20 條以內兩批之間停 10 分鐘。如果賬號本身沒有實名或綁卡還需要在這個基礎上再保守一倍。這個參數(shù)沒有商量余地寧慢勿快。5.3 腳本報“pipe not found”或“connect fail”現(xiàn)象啟動調度腳本后立刻報pipe not found注入端日志顯示沒有任何連接進入。原因微信進程已經在注入器之前啟動了DLL 無法掛載到已加載的進程上或者管道名在注入器和調度腳本兩邊不一致。Windows 下命名管道的連接失敗九成是這兩個原因。解決先taskkill /IM WeChat.exe /F把微信進程徹底結束再以管理員身份運行注入器等它輸出“inject success”后再啟動 Python 調度端。同時核對兩邊的--pipe參數(shù)字符串大小寫和末尾數(shù)字都要完全一致。5.4 接口沒有報錯但添加按鈕一直是灰色現(xiàn)象某些wxid傳入后注入層成功返回但微信界面里對應搜索結果顯示的是灰色不可點按鈕。原因對方的隱私設置關閉了“通過搜索添加”或者該賬號當前處于風險狀態(tài)微信不允許通過任何接口觸達。這類賬號在接口層面沒有明確錯誤碼屬于數(shù)據(jù)本身不可用。解決把這批wxid從正式隊列里摘出來單獨放進一個“不可用名單”不要再重試。反復重試不會提高成功率反而會讓整個賬號的權重被拉低。5.5 代碼改完重啟日志沒有任何輸出現(xiàn)象修改了驗證語模板后重新啟動調度腳本終端窗口干干凈凈既沒有錯誤也沒有正常日志。原因Python 的 stdout 在 Windows 下默認有緩沖加上程序跑了幾分鐘后才打印日志全被吞在緩沖區(qū)里另一個常見原因是腳本里用了print但沒加flushTrue進程異常退出時內容還沒來得及落盤。解決啟動命令里加PYTHONUNBUFFERED1或者把日志統(tǒng)一寫進文件而不是終端。我在代碼包里默認就是寫兩路日志一份終端實時輸出一份runtime.log落盤這樣即使終端關掉了后續(xù)也能靠文件排查問題。6. 把添加結果變成可回查的賬單回調校驗與定時巡檢6.1 真實成功的判定雙確認機制發(fā)送回執(zhí)為 0只能說明請求被微信接收不能說明對方已經看到并處理。想要知道真實觸達結果需要第二層數(shù)據(jù)微信收到“朋友驗證通知”后產生的事件回調以及對方通過好友請求后觸發(fā)的好友列表變動。我把這個邏輯叫雙確認。第一確認是發(fā)送回執(zhí)來自請求接口本身第二確認是事件回調來自微信內部的消息推送。兩段日志對得上才算一條真實成功記錄。具體做法是在調度端保留一張sent記錄表回調解析器收到friend_add_event時把對應的wxid標記為“已接收”。# 把事件回調單獨掛一個監(jiān)聽進程不跟發(fā)送進程混在一起 python monitor.py --pipe wxrpc_7001 --event friend_add --db result.sqlite這樣回調解析和發(fā)送調度互相獨立即使發(fā)送進程崩了回調進程也能持續(xù)積累數(shù)據(jù)下次重啟后去重補發(fā)就行。6.2 定時巡檢與紅黃牌機制批量添加不是一次性腳本它需要持續(xù)跑所以要給隊列加一道巡檢機制。我把每天的運行時段拆成上午、下午、晚上三段每段結束后對result.sqlite做一次統(tǒng)計新增了多少條白名單命中、多少條超時未回執(zhí)、多少條被風控攔截。對于超過 120 秒還沒有任何回執(zhí)的請求標記為黃牌同一條數(shù)據(jù)連續(xù)黃牌兩次就升級為紅牌直接踢出隊列。這個機制解決的是“腳本卡死但進程還活著”的尷尬場面——沒有它你可能過了半天才發(fā)現(xiàn)某批數(shù)據(jù)全部阻塞在管道讀寫上。從那以后我每次換微信版本或者改scene參數(shù)都強制在小號上跑一遍三個檢查發(fā)送回執(zhí)為 0、對方真實收到申請、通過后回調入庫。三道都綠了才輪到正式數(shù)據(jù)進隊列。這套流程看著慢但省下的全是踩坑的時間希望幫到你。本文還有配套的精品資源點擊獲取