前言
在私域运营、客户触达、社群增长等场景中,手动添加微信好友的效率极低——人工一天能处理的数量非常有限,而且稍不留意就会因操作频率异常被微信风控封号。越来越多的开发者和运营团队开始考虑通过程序化方式来完成"加好友"和"通过好友申请"这两个高频动作。
私域流量的核心在于"人",而把潜在用户加进微信好友,是私域运营的第一步。一旦好友关系建立,后续的触达成本极低,转化路径也远比公域广告短。正因如此,如何高效、安全地批量建立好友关系,成为很多团队的技术痛点。
本文聚焦于以下三个核心问题:
- 如何用程序搜索微信号并发起好友申请?
- 如何自动批量通过待处理的好友请求?
- 如何在两个操作中设置合理的频率控制,避免触发微信风控?
文章给出完整的 Python 示例代码,并附上经过实测验证的频率参数建议,适合有一定 Python 基础的开发者参考实践。
一、技术方案整体设计
1.1 方案选型对比
实现微信自动化操作,目前主要有以下几类技术路径:
| 方案 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| Xposed/Hook 注入 | 在 Android 层 hook 微信函数 | 控制粒度细 | 需要 root、维护成本高、随微信版本更新频繁失效 |
| 模拟点击(UIAutomator/ADB) | 识别屏幕控件并点击 | 无需逆向 | 不稳定、速度慢、UI 变化即失效 |
| 协议层封包 | 模拟微信通信协议 | 速度快 | 违反协议难度大、风险高 |
| 托管 HTTP API | 平台维护协议层,开发者调 HTTP 接口 | 开发简单、无需关心底层 | 依赖第三方服务稳定性 |
对于不熟悉微信底层协议的开发者,托管 HTTP API 是接入成本最低、最适合快速落地的方案。本文的代码示例基于此方案编写。
1.2 整体流程
扫码登录 → 获取 appId
↓
构建待加好友列表(微信号/手机号)
↓
循环:搜索微信号 → 发起好友申请 → 随机等待
↓
定时轮询:拉取好友申请列表 → 批量通过 → 随机等待
1.3 准备工作与注意事项
在开始编码之前,有几项准备工作不能省:
账号选择:用于执行自动化操作的微信账号,最好是"健康度"较高的老号——有正常聊天记录、绑定了手机号和银行卡、朋友圈有内容。新注册或刚激活的账号风控阈值极低,极易被封。
设备环境:使用固定 IP 的服务器或真实手机设备。频繁切换 IP(尤其是跨城市)会触发设备异常告警。如果在云服务器上运行,建议固定出口 IP,并与日常登录环境保持一致。
目标列表质量:待添加的微信号列表要事先做基本校验——去除明显无效的格式、剔除重复项。搜索不存在的账号虽然不会直接封号,但会消耗接口配额并影响操作节奏。
合规意识:批量加好友属于高频敏感操作,务必在合法合规的业务场景下使用,不得用于骚扰、诈骗等违规行为。以官方文档为准了解平台使用条款。
二、登录与初始化
2.1 扫码登录流程
所有操作都需要一个已登录的微信设备,通过扫码登录接口获取 appId,后续所有请求都携带这个参数。
pythonimport requests
import time
import random
BASE = "https://你的接口域名" # 注册后在官方文档获取
TOKEN = "你的Token"
APPID = "你的appId" # 扫码登录后获得
HEADERS = {"token": TOKEN} # 鉴权字段名以官方文档为准
def get_login_qrcode():
"""获取登录二维码"""
url = f"{BASE}/login/getLoginQrCode"
resp = requests.post(url, headers=HEADERS, json={})
data = resp.json()
if data.get("ret") == 200:
# 返回二维码图片 url,扫码后调用 checkLogin 轮询状态
return data["data"]
return None
def check_login(uuid):
"""轮询登录状态,登录成功后返回 appId"""
url = f"{BASE}/login/checkLogin"
for _ in range(60): # 最多等 60 秒
resp = requests.post(url, headers=HEADERS, json={"uuid": uuid})
data = resp.json()
if data.get("ret") == 200 and data["data"].get("status") == 2:
return data["data"]["appId"]
time.sleep(1)
return None
代码为示例,具体接口路径和字段名以官方文档为准。
2.2 登录后的状态维护
登录成功后,appId 需要持久化保存(写入本地文件或数据库),避免每次重启程序都重新扫码。同时建议添加登录状态检测逻辑——部分接口在 token 过期后会返回特定错误码,程序应能捕获并触发重新登录流程,而不是静默失败。
三、自动加好友实战
3.1 搜索微信号
发起好友申请前,先调用搜索接口确认对方账号存在且可被添加:
pythondef search_contact(wxid_or_phone: str):
"""搜索微信号或手机号,返回用户信息"""
url = f"{BASE}/contacts/search"
payload = {
"appId": APPID,
"contactsInfo": wxid_or_phone
}
resp = requests.post(url, headers=HEADERS, json=payload)
data = resp.json()
if data.get("ret") == 200:
return data.get("data") # 包含 wxid、昵称、头像等
return None
搜索成功后,从返回数据中取出 wxid(微信 ID),用于后续的好友申请。
搜索阶段的常见问题:
- 对方账号注销或封号后搜索返回空,需在代码里做
None判断,否则后续操作会报错。 - 手机号搜索受对方隐私设置影响,对方若设置了"不允许通过手机号搜索",则搜索无结果。此时可先尝试微信号再回退手机号,两种方式都失败则跳过。
- 搜索接口本身也有频率限制,连续高频搜索(超过每分钟 10 次)会引发警告,代码中即便是搜索失败的情况也应等待一定时间再继续。
3.2 发起好友申请
pythondef add_contact(wxid: str, remark: str = "", verify_msg: str = "你好,我是xxx"):
"""向指定 wxid 发送好友申请"""
url = f"{BASE}/contacts/addContacts"
payload = {
"appId": APPID,
"wxId": wxid,
"remark": remark, # 备注名(选填)
"msg": verify_msg # 验证消息
}
resp = requests.post(url, headers=HEADERS, json=payload)
return resp.json()
验证消息的撰写建议: 固定的验证消息是风控的重要信号之一。建议准备 8-15 条不同措辞的申请语,运行时随机选取一条,同时根据业务场景做个性化替换(如插入对方公司名、活动名称等),使每条申请看上去都像真人手写。
3.3 批量加好友主循环(含频率控制)
这里是防封的核心——频率参数必须严格遵守,不能图省事把间隔设为 0:
pythondef batch_add_contacts(target_list: list, daily_limit: int = 10):
"""
批量加好友。
target_list: 微信号或手机号列表
daily_limit: 每天上限,建议新号 5-10,老号 10-15
"""
added_today = 0
# 每 2 小时内不超过 5 个
batch_size = 5
batch_interval_seconds = 2 * 3600 # 2 小时
i = 0
while i < len(target_list) and added_today < daily_limit:
batch = target_list[i: i + batch_size]
for target in batch:
if added_today >= daily_limit:
print(f"[STOP] 今日已达上限 {daily_limit} 个,停止。")
return
# Step 1: 搜索
user_info = search_contact(target)
if not user_info:
print(f"[SKIP] 搜索不到:{target}")
# 搜索失败也要等待,避免连续请求
time.sleep(random.uniform(15, 30))
continue
wxid = user_info.get("wxid")
if not wxid:
continue
# Step 2: 发申请
result = add_contact(wxid, verify_msg="你好,我是某某某")
if result.get("ret") == 200:
added_today += 1
print(f"[OK] 已申请:{target}(今日第 {added_today} 个)")
else:
print(f"[FAIL] 申请失败:{target},原因:{result.get('msg')}")
# Step 3: 随机等待 3-8 分钟(模拟人工间隔)
wait = random.uniform(180, 480)
print(f" → 等待 {wait:.0f}s 后继续…")
time.sleep(wait)
i += batch_size
# 每批 5 个后等待约 2 小时
if i < len(target_list) and added_today < daily_limit:
print(f"[BATCH] 本批完成,等待 {batch_interval_seconds//3600} 小时后继续…")
time.sleep(batch_interval_seconds + random.uniform(-300, 300))
关于频率随机性的补充说明: 微信风控算法对"机械规律"非常敏感。固定间隔(比如每隔刚好 5 分钟)和随机间隔(3-8 分钟浮动)在系统眼里差异显著。random.uniform 给出的浮动区间越自然,越接近人工操作的不规则节奏,被识别为机器人的概率越低。建议将随机范围设置得稍宽一些,不要过于精确。
四、自动通过好友申请
4.1 获取待通过的好友申请列表
微信会把别人发来的好友请求存在"新的朋友"列表里,通过 API 可以拉取这个列表:
pythondef get_pending_friend_requests():
"""拉取待通过的好友申请列表"""
url = f"{BASE}/contacts/getNewFriends" # 接口名以官方文档为准
payload = {"appId": APPID}
resp = requests.post(url, headers=HEADERS, json=payload)
data = resp.json()
if data.get("ret") == 200:
return data.get("data", {}).get("list", [])
return []
返回的列表中,每条申请一般包含:申请人 wxid、验证消息、申请时间戳等字段(以文档为准)。
注意申请时效性: 微信好友申请有时效限制,超过一定时间(通常为 3 天)未通过的申请会自动失效。因此轮询频率不宜设置得过低——建议每 30 分钟检查一次,确保及时处理。同时程序应记录已处理过的申请 ID,避免因接口返回历史记录而重复通过。
4.2 批量通过申请(含防封频率)
pythondef accept_friend_request(scene: int, v3: str, v4: str):
"""
通过好友申请。
scene、v3、v4 从申请列表返回数据中取,具体字段以官方文档为准。
"""
url = f"{BASE}/contacts/agreeApply"
payload = {
"appId": APPID,
"scene": scene,
"v3": v3,
"v4": v4
}
resp = requests.post(url, headers=HEADERS, json=payload)
return resp.json()
def batch_accept_all(max_per_day: int = 150):
"""
批量通过所有待处理申请。
max_per_day: 每天被动通过上限,建议 ≤200
"""
requests_list = get_pending_friend_requests()
if not requests_list:
print("[INFO] 没有待通过的申请。")
return
accepted = 0
for req in requests_list:
if accepted >= max_per_day:
print(f"[STOP] 今日通过已达 {max_per_day} 个上限。")
break
scene = req.get("scene")
v3 = req.get("v3")
v4 = req.get("v4")
if not (v3 and v4):
print(f"[SKIP] 申请字段不完整,跳过。")
continue
result = accept_friend_request(scene, v3, v4)
if result.get("ret") == 200:
accepted += 1
print(f"[OK] 已通过第 {accepted} 个好友申请")
else:
print(f"[FAIL] 通过失败:{result.get('msg')}")
# 每次通过后随机等待 5-20 秒
wait = random.uniform(5, 20)
time.sleep(wait)
print(f"[DONE] 本轮共通过 {accepted} 个好友申请。")
4.3 定时轮询:每隔 30 分钟自动执行一次
pythonimport schedule
def job():
print(f"[{time.strftime('%H:%M:%S')}] 开始轮询好友申请…")
batch_accept_all(max_per_day=150)
schedule.every(30).minutes.do(job)
if __name__ == "__main__":
print("启动好友申请自动通过服务…")
while True:
schedule.run_pending()
time.sleep(1)
五、防封频率参数总结
微信的风控系统对频率异常非常敏感,以下是经过实践验证的参数区间:
5.1 主动加好友
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 每日总上限 | 5-15 个 | 新号 5-10,老号可适当放宽到 15 |
| 每 2 小时上限 | ≤5 个 | 分批控制,避免短时间密集 |
| 单次申请间隔 | 3-8 分钟(随机) | 必须随机,固定间隔同样会被识别 |
| 批次间隔 | 约 2 小时 | 每批 5 个后等满 2 小时 |
| 新号暖机期 | 正常使用 3 天后再发申请 | 刚激活的号频率要求更严格 |
| 搜索频率 | 10-20 次/天 | 搜索本身也会计入频率 |
5.2 被动通过好友申请
| 参数 | 推荐值 | 说明 |
|---|---|---|
| 每日通过上限 | ≤200 个 | 超过后次日再通过 |
| 单次通过间隔 | 5-20 秒(随机) | 机器人节奏 vs 人工节奏的主要差异 |
| 轮询检查间隔 | 30 分钟一次 | 不要每秒轮询 |
5.3 其他辅助建议
- 验证消息要有变化:固定的申请语也是风控信号,可以准备 5-10 条随机轮换。
- 账号健康度很重要:被操作的号要保持正常的聊天、朋友圈等行为,不能只加人。
- 网络环境稳定:频繁换 IP 容易触发设备异常风控。
- 回调监听申请消息:通过
setCallback设置回调地址,当有人主动申请时会实时收到推送,比轮询更及时。
5.4 遭遇风控后的处理策略
即使做好了频率控制,运营过程中仍可能遭遇风控提示(如"操作频繁,请稍后再试")。此时不要反复重试,正确的处置步骤是:
- 立即暂停所有自动化操作,停止时间不少于 24 小时。
- 在此期间用该账号进行正常人工操作:回复消息、发朋友圈、点赞等,恢复账号健康信号。
- 恢复后将每日上限下调 30%-50%,观察 3-5 天稳定运行再逐步回调。
- 如果反复触发风控,考虑更换账号或降低自动化程度,改为半自动辅助操作。
六、通过回调实时通过好友申请
上面的轮询方式有一定延迟,更推荐的方式是配置回调:
pythonfrom flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/wechat/callback", methods=["POST"])
def wechat_callback():
"""接收微信消息回调,收到好友申请后自动通过"""
payload = request.json
msg_type = payload.get("type")
# type==37 通常为好友申请消息,具体以官方文档的消息类型定义为准
if msg_type == 37:
v3 = payload.get("v3")
v4 = payload.get("v4")
scene = payload.get("scene", 3)
if v3 and v4:
# 收到申请后等 5-15 秒再通过,模拟人工操作
time.sleep(random.uniform(5, 15))
result = accept_friend_request(scene, v3, v4)
print(f"[CALLBACK] 自动通过好友申请:{result}")
# 必须返回 200,否则平台会重试推送
return jsonify({"code": 200}), 200
# 注册回调地址(服务器公网可访问)
def register_callback(callback_url: str):
url = f"{BASE}/login/setCallback"
payload = {
"appId": APPID,
"callbackUrl": callback_url
}
resp = requests.post(url, headers=HEADERS, json=payload)
print("注册回调结果:", resp.json())
if __name__ == "__main__":
register_callback("https://你的公网域名/wechat/callback")
app.run(host="0.0.0.0", port=8080)
回调使用要点:
- 回调服务必须公网可访问,本地 localhost 无法被平台调用。
- 收到推送后必须返回 HTTP 200,否则平台会在短时间内重复推送同一条消息。
- 主动发出的消息(如自己发的申请确认)不会触发回调,只有对方操作才会推送。
回调服务的部署建议: 回调服务可以部署在任何有公网 IP 的云服务器上。如果本地开发调试,可以临时使用 ngrok 等内网穿透工具暴露本地端口,但生产环境必须使用稳定的公网地址。同时建议在回调入口加入请求签名校验,防止恶意第三方伪造推送数据。
七、关于托管 API 的简要说明
本文示例所基于的方案中,WechatApi 提供扫码登录、消息收发、好友与群管理等 REST 接口,HTTP 调用即可,无需自行维护协议层,适合快速接入的开发团队。
总结
本文从方案选型、登录初始化、主动加好友、自动通过申请到回调实时处理,完整梳理了微信机器人自动加好友的实现链路。其中频率控制是整套方案的关键:每日加好友 5-15 个、每批间隔 2 小时、单次随机等待、被动通过不超过 200/天,这些参数直接决定账号能否长期稳定运行。
在实际落地过程中,有几点值得重点关注:账号本身的健康度决定了上限;网络和设备环境的稳定性影响风控判断;验证消息的多样性和随机等待的自然性是规避机器识别的关键细节。遭遇风控时及时暂停并让账号"休养",往往比继续强行推进效果更好。
代码示例仅供参考,具体接口字段请以官方文档为准。
