首页 / 博客 / API·多语言·接口

微信获取好友列表接口(分页与增量)

分类:API·多语言·接口 · 标签:微信获取好友列表接口、个人微信API、好友列表分页增量同步

前言

做过微信私域运营或SCRM系统的开发者,几乎都会遇到同一个难题:如何把账号的好友列表稳定地同步到自己的系统里?微信官方不对个人号开放好友接口,第三方Hook方案则存在封号风险,且无法在服务器上稳定运行。好友数量一旦超过几千人,如何做分页拉取、如何识别新增好友、如何处理删除或拉黑——这些细节问题往往让开发者耗费大量时间踩坑。本文基于 WechatApi 个人微信API 平台,系统讲解好友列表接口的调用方式、分页机制与增量同步方案,附带可直接参考的代码示例。

一、好友列表同步的核心挑战

微信个人号的通讯录体量差异极大:普通用户可能只有几百个好友,私域运营账号则可能高达数千甚至接近微信官方上限(约5000人)。在设计好友列表同步功能时,以下几个挑战必须在架构层面提前考量。

全量拉取的性能问题。 直接一次性获取数千条好友记录,不仅响应时间长、超时概率高,还会对宿主设备产生明显压力。合理的做法是分页拉取,每页返回固定数量(如100条),分批写入本地数据库。

增量同步的识别问题。 全量同步只需在初始化时执行一次,此后应以增量模式运行:只拉取上次同步之后新增或发生变化的好友。如果不做增量区分,每次全量对比几千条记录会带来不必要的计算开销,并且在高频场景下容易产生脏数据。

删除与拉黑的检测问题。 微信本身不会主动推送"对方删除了你"的事件。检测好友关系变化,通常需要结合好友列表的全量快照与消息触达状态来综合判断,需要在业务层设计对应的比对逻辑。

多账号并发管理。 在私域运营场景中,往往需要同时管理数十甚至上百个微信账号。每个账号对应一个独立的 appId(设备ID),好友列表接口需要在请求参数中明确指定 appId,才能保证数据隔离与并发安全。

WechatApi 基于 iPad 协议实现微信接口能力,在服务器端稳定运行,规避了 PC Hook 方案的封号风险,也无需在本地安装客户端。对于需要处理上述挑战的开发者,这是目前生产环境中较为可靠的选择。

二、接口鉴权与请求规范

WechatApi 平台的所有接口均采用统一的 HTTP POST + JSON 规范,鉴权信息通过请求头传递,业务参数放在请求体中。

请求头格式

字段名类型说明
VideosApi-tokenstring控制台获取的 API Token,每个账户唯一
Content-Typestring固定为 application/json

通用请求体参数

参数名类型必填说明
appIdstring设备ID,登录微信账号后由平台分配,多账号并发时用于区分不同设备
pageIndexint分页页码,从 0 开始,默认 0
pageSizeint每页返回条数,建议 50~200,默认 100
lastSyncTimestring增量同步时传入上次同步的时间戳(Unix 秒),仅返回该时间之后有变化的好友

通用返回体结构

所有接口均返回统一的 JSON 结构:

json{
  "ret": 200,
  "msg": "success",
  "data": {
    "total": 3268,
    "pageIndex": 0,
    "pageSize": 100,
    "hasMore": true,
    "list": [
      {
        "wxId": "wxid_xxxxxxxxxxxxxxx",
        "nickname": "张三",
        "remark": "客户-张三",
        "avatar": "https://wx.qlogo.cn/...",
        "sex": 1,
        "city": "上海",
        "province": "上海",
        "addTime": 1700000000,
        "isFriend": true,
        "isBlocked": false
      }
    ]
  }
}

ret 为 200 表示成功,其余错误码(如 401 鉴权失败、500 设备离线)需在业务层做异常处理。hasMore 字段是分页控制的核心依据,只要为 true 就应继续请求下一页。

三、分页拉取:全量同步实现

全量同步通常在以下场景触发:首次接入某个微信账号、手动触发一次全量刷新、或者增量同步积累误差后的修复。

以下是一个 Python 实现的分页拉取示例,展示了完整的分页循环逻辑:

pythonimport requests
import time

API_BASE = "https://api.example-wechatapi.net"   # 示意域名,以控制台实际地址为准
TOKEN = "your_videosapi_token_here"
APP_ID = "your_app_id_here"

HEADERS = {
    "VideosApi-token": TOKEN,
    "Content-Type": "application/json"
}

def fetch_all_friends(app_id: str) -> list:
    """全量分页拉取好友列表"""
    all_friends = []
    page_index = 0
    page_size = 100

    while True:
        payload = {
            "appId": app_id,
            "pageIndex": page_index,
            "pageSize": page_size
        }
        resp = requests.post(
            f"{API_BASE}/friend/list",
            headers=HEADERS,
            json=payload,
            timeout=30
        )
        result = resp.json()

        if result.get("ret") != 200:
            print(f"[ERROR] page={page_index}, msg={result.get('msg')}")
            break

        data = result["data"]
        friends = data.get("list", [])
        all_friends.extend(friends)

        print(f"[INFO] 已拉取 {len(all_friends)}/{data['total']} 条")

        if not data.get("hasMore", False):
            break

        page_index += 1
        time.sleep(0.5)   # 适当限速,避免触发频控

    return all_friends

if __name__ == "__main__":
    friends = fetch_all_friends(APP_ID)
    print(f"[DONE] 共获取好友 {len(friends)} 人")

几个值得注意的实现细节:

四、增量同步:只拉取新增好友

全量同步完成后,日常运营中只需要知道"上次同步之后新增了哪些好友"。通过 lastSyncTime 参数,接口会只返回 addTime 大于该时间戳的好友记录,大幅减少数据量和请求次数。

pythonimport requests
import time
import json
from pathlib import Path

API_BASE = "https://api.example-wechatapi.net"
TOKEN = "your_videosapi_token_here"
APP_ID = "your_app_id_here"
SYNC_STATE_FILE = f"/tmp/wechatapi_sync_{APP_ID}.json"

HEADERS = {
    "VideosApi-token": TOKEN,
    "Content-Type": "application/json"
}

def load_last_sync_time() -> int:
    """从本地状态文件读取上次同步时间"""
    p = Path(SYNC_STATE_FILE)
    if p.exists():
        state = json.loads(p.read_text())
        return state.get("lastSyncTime", 0)
    return 0

def save_last_sync_time(ts: int):
    """保存本次同步时间"""
    Path(SYNC_STATE_FILE).write_text(json.dumps({"lastSyncTime": ts}))

def fetch_incremental_friends(app_id: str, last_sync_time: int) -> list:
    """增量拉取:只获取 last_sync_time 之后新增的好友"""
    new_friends = []
    page_index = 0
    current_time = int(time.time())

    while True:
        payload = {
            "appId": app_id,
            "pageIndex": page_index,
            "pageSize": 100,
            "lastSyncTime": str(last_sync_time)
        }
        resp = requests.post(
            f"{API_BASE}/friend/list",
            headers=HEADERS,
            json=payload,
            timeout=30
        )
        result = resp.json()

        if result.get("ret") != 200:
            print(f"[ERROR] {result.get('msg')}")
            break

        data = result["data"]
        new_friends.extend(data.get("list", []))

        if not data.get("hasMore", False):
            break

        page_index += 1
        time.sleep(0.5)

    # 同步成功后更新时间戳
    if new_friends:
        save_last_sync_time(current_time)
        print(f"[INFO] 增量同步到 {len(new_friends)} 个新好友")
    else:
        print("[INFO] 无新增好友")

    return new_friends

if __name__ == "__main__":
    last_sync = load_last_sync_time()
    print(f"[INFO] 上次同步时间: {last_sync}")
    new = fetch_incremental_friends(APP_ID, last_sync)

增量同步的时间戳管理是整个方案的关键。推荐做法:

  1. 时间戳以服务端当前时间为准,而不是取返回数据中最后一条的 addTime。防止服务端时钟与本地时钟不一致导致遗漏。
  2. 状态文件或数据库中同时记录同步状态(成功/失败),失败时不更新时间戳,下次重新从上一个成功的时间点拉起。
  3. 定时任务频率:增量同步可以跑得比较频繁,5~15分钟一次是合理区间。全量同步建议每天凌晨执行一次作为兜底校正。

五、返回字段详解与数据库设计建议

好友列表接口返回的每条记录包含丰富的字段,合理利用这些字段可以支撑更多业务场景。

字段类型说明运营价值
wxIdstring微信唯一标识(wxid_xxx),稳定不变主键,用于去重和关联
nicknamestring好友当前昵称定期更新,检测昵称变化
remarkstring我方对该好友的备注名SCRM系统中的客户标识
avatarstring头像URL可缓存到自有CDN
sexint性别(0未知,1男,2女)用户画像分析
city / provincestring城市/省份(用户自填,可能为空)地域分层运营
addTimeint加好友时间(Unix秒)增量同步的核心字段
isFriendbool是否互为好友(对方是否也加了我)单向关注检测
isBlockedbool是否被拉黑清理无效好友

在数据库设计上,建议以 (appId, wxId) 作为联合主键,支持多账号数据隔离。同时在 addTimesync_updated_at 上建索引,方便按时间范围查询。对于 SCRM 系统,可以在好友表上扩展自定义标签字段,与接口返回的原始字段分开存储。

如果你在做企业私域运营系统,这部分能力正是 WechatApi 微信API对接微信二次开发 场景的核心需求之一,平台文档中对多账号并发场景有更详细的说明。

六、Shell 脚本快速验证接口

在正式接入之前,可以用 curl 快速验证接口连通性和返回格式,不需要写任何代码:

bashcurl -X POST "https://api.example-wechatapi.net/friend/list" \
  -H "VideosApi-token: your_videosapi_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "appId": "your_app_id_here",
    "pageIndex": 0,
    "pageSize": 5
  }' | python3 -m json.tool

如果返回 ret: 200data.list 中有好友数据,说明鉴权和设备绑定均正常。若返回 401,检查 Token 是否正确传入请求头;若返回设备离线类错误,需要先在控制台确认微信账号的在线状态。

登录控制台与申请 Token 的入口:https://newmanager.wechatapi.net/dashboard/

七、常见问题与注意事项

Q:好友列表拉取到一半中断了,需要从头开始吗?

不需要。保存当前 pageIndex 到本地状态,下次直接从中断的页码继续请求即可。建议每成功拉取10页就持久化一次进度。

Q:isFriend 为 false 是什么含义?

表示对方没有把你加为好友,也就是单向关注状态。这种情况下你仍然可以给对方发消息(对方未删除你),但对方无法主动给你发消息。在私域运营中,isFriend 为 false 的联系人通常需要单独处理(如发送添加提示)。

Q:addTime 的精度如何?能否依赖它做毫秒级精确增量?

addTime 精度为秒级。在设计增量同步时,建议将上次同步时间向前偏移 5~10 秒作为安全余量,避免因网络延迟导致边界数据丢失,代价只是少量重复记录(可在写入时用主键去重处理)。

Q:接口有频率限制吗?

平台侧有合理的频率控制,建议相邻请求间隔不低于 300ms。全量同步期间每页间隔 500ms 是稳健选择。如有更高并发需求,可联系平台申请提升配额。

Q:能否通过好友列表接口检测到"被删除"?

接口本身不推送删除事件。通常做法是:定期全量快照与本地数据库做 diff,若某个 wxId 之前存在、现在消失,则标记为"疑似被删"。结合发送一条消息后检测 isFriend 状态变化,可以进一步确认。这属于业务层的检测逻辑,与接口本身无关。

Q:iPad协议与PC Hook方案的好友列表接口有什么区别?

微信iPad协议 是在服务端模拟 iPad 客户端与微信服务器通信,数据来源与真实设备完全一致,且不依赖本地安装微信客户端,稳定性更高、更适合服务器常驻运行。PC Hook 方案需要在 Windows 机器上运行并注入微信进程,维护成本高,微信版本更新时频繁失效。对于需要长期稳定运行的生产系统,iPad 协议方案是更合理的选择。

小结

微信好友列表的稳定同步,看似简单,实际涉及分页控制、增量识别、时间戳管理、多账号隔离等多个工程细节。本文梳理了基于 WechatApi 平台实现全量分页拉取和增量同步的完整方案:全量同步用于初始化和定期校正,增量同步覆盖日常运营的新增好友识别,两者结合可以在保证数据准确性的同时最小化资源消耗。

如果你正在构建私域运营系统、微信客服机器人 或 SCRM 平台,好友列表接口往往是数据流的起点。WechatApi 平台文档(post.wechatapi.net)提供了完整的接口参考,控制台(newmanager.wechatapi.net/dashboard)支持在线测试与 Token 管理,可以作为开发验证的起点。

想动手试试?

WechatApi 提供扫码登录、消息收发、好友与群管理等 REST 接口,注册后几分钟跑通。

立即免费注册查看开发文档

相关产品页

🔗 个人微信API(产品页)🔗 微信iPad协议(产品页)🔗 微信二次开发(产品页)

相关文章

微信API接口返回失败/收不到消息?完整排查清单微信 API 怎么对接?Python 发出第一条消息实战Node.js 微信机器人开发教程(发消息 + 收回调)个人微信API能力清单:消息/好友/群/朋友圈接口一览
© 2025 WechatApi · 企业级微信智能机器人接入平台
官网价格帮助文档博客
苏ICP备2024128799号 · 苏ICP备2023038368号