☰
【uiautomation】微信好友列表获取并存储到txt:TaoToken 统一 Key 通道下的自动化脚本配置
2026/10/1 14:34:24 网站建设 项目流程

1. 为什么我要用 uiautomation 抓微信好友列表

微信 PC 端本身不提供任何导出好友列表的入口,通讯录管理页面虽然能看到全部联系人,但只能一屏一屏往下滚,手动复制粘贴几百个好友基本不现实。我最早是用截图 + OCR 的方式做,识别率受昵称里的特殊符号影响很大,后来换成 uiautomation 直接读取控件树里的文本,准确率一下就上来了。

uiautomation 是 Python 的一个第三方库,底层调用的是 Windows 的 UI Automation 接口,能直接拿到窗口里每个控件的 Name、ClassName、ControlType 等属性。微信 PC 端的通讯录管理窗口是一个标准的 ListControl,每个联系人就是一个 ListItemControl,里面的昵称挂在 TextControl 上。我们要做的就是:打开微信 → 进入通讯录管理 → 定位列表控件 → 循环滚动读取 → 去重后写入 txt。

这套流程适合谁?适合需要批量整理微信好友、做私域运营统计、或者单纯想备份一份好友名单的人。前提是你得在 Windows 上操作,因为 uiautomation 只支持 Windows 平台。另外微信版本不同,控件名称可能有细微差异,我会在排障章节里给出定位方法。

整个脚本的核心难点有三个:一是滚动加载,微信的列表是虚拟列表,不滚动就不会渲染后面的联系人;二是去重,滚动过程中同一个联系人可能被重复读到;三是判断到底,目前没有特别可靠的 API 能直接判断列表是否滚到底,我采用的是人工按空格键触发最后一轮全量读取的方式。

在写脚本之前,我先把凭证管理这块理顺了。因为脚本后续可能要调用一些模型接口做昵称清洗或者分类,如果每个脚本都硬编码 Key,维护起来很麻烦。我试过用 TaoToken 的统一 Key 通道来管理这些调用凭证,一个 Key 走所有模型,省得来回切换。下面先把这块配置讲清楚,再进入 uiautomation 的实操。

2. TaoToken 统一 Key 通道的前置配置

TaoToken 是一个模型调用凭证的统一管理通道,官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。它的作用是让你用一个 Key 就能调用多个模型,不用为每个模型单独申请和配置密钥。对于我这种经常写自动化脚本、时不时要加个模型调用做后处理的人来说,省了不少事。

先说你需要在脚本里用到的三件套:Base URL、API Key、Model ID。Base URL 固定填 https://taotoken.net/api ,API Key 在控制台创建,Model ID 根据你要用的模型填,比如 claude-sonnet-4-20250514 或者 gpt-4o 这类。这三个东西在后面的配置片段里会反复出现,先记牢。

创建 Key 的路径是:登录后进入控制台,找到 API Keys 页面,点新建,复制生成的 Key。这个 Key 只显示一次,记得存好。如果你用的是 Claude Code 或者 Cline 这类工具,配置方式略有不同,但核心三件套是一样的。

我建议把 Key 放在环境变量里,而不是直接写在脚本中。Windows 下可以这样设置:

setx TAOTOKEN_API_KEY "sk-你的实际Key"

设置完之后需要重开终端才能生效。然后在 Python 脚本里用 os.environ 读取:

import os api_key = os.environ.get("TAOTOKEN_API_KEY") base_url = "https://taotoken.net/api" model_id = "claude-sonnet-4-20250514"

如果你用的是 settings.json 或者 config.toml 这类配置文件,格式如下。以 Claude Code 的 settings.json 为例,路径通常在用户目录下的 .claude 文件夹里:

{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的实际Key", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }

注意 Base URL 后面不要加 /v1 或者其他路径,直接就是 https://taotoken.net/api 。Model ID 要和你实际使用的模型对应,填错了会报 model not found。API Key 如果泄露了,去控制台删掉重新建一个就行,不影响其他配置。

配置好之后,你可以先用一个最简单的请求验证通道是否通。Python 里用 requests 发一个 chat completions 请求:

import requests import os url = "https://taotoken.net/api/v1/chat/completions" headers = { "Authorization": f"Bearer {os.environ.get('TAOTOKEN_API_KEY')}", "Content-Type": "application/json" } data = { "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "回复ok"}] } resp = requests.post(url, headers=headers, json=data, timeout=30) print(resp.status_code) print(resp.json())

如果返回 200 并且 choices 里有内容,说明通道没问题。如果返回 401,检查 Key 是否复制完整;如果返回 404,检查 URL 路径是否写对。这一步验证通过之后,再回到 uiautomation 的主线任务。

3. uiautomation 抓取微信好友列表的可复制配置

现在进入正题。先安装 uiautomation:

pip install uiautomation

安装完成后,你需要知道微信的安装路径。在桌面微信图标上右键 → 打开文件所在的位置,就能看到 WeChat.exe 的完整路径。把这个路径填到脚本里的 subprocess.Popen 中。

下面是完整的配置片段,我把它拆成几个部分讲。第一部分是启动微信和进入通讯录管理:

import subprocess import uiautomation as auto import time # 替换成你自己的微信路径 wechat_path = r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe" subprocess.Popen(wechat_path) time.sleep(3) # 等微信窗口加载 wechat_window = auto.WindowControl( searchDepth=1, className='WeChatMainWndForPC', Name='微信' ) # 点击通讯录按钮 contact_btn = wechat_window.ButtonControl(Name='通讯录') contact_btn.Click() time.sleep(1) # 点击通讯录管理 admin_btn = wechat_window.ButtonControl(Name="通讯录管理") admin_btn.Click() time.sleep(1)

这里有几个坑要注意。第一,微信路径如果包含空格,用 r"" 原始字符串避免转义问题。第二,time.sleep 的时长根据你机器性能调整,太短了窗口还没渲染出来就去找控件会报 NoneType。第三,className 和 Name 必须和实际窗口一致,可以用 auto.WindowControl 的 Inspect 工具查看。

第二部分是定位通讯录管理窗口和列表控件:

comm_admin = auto.WindowControl( Name="通讯录管理", ClassName="ContactManagerWindow" ) # 把鼠标移到窗口中心,让滚轮对列表生效 comm_admin.MoveCursorToMyCenter() time.sleep(0.5) list_ctrl = comm_admin.ListControl(Name="")

MoveCursorToMyCenter 这行很关键。微信的通讯录管理窗口里,联系人列表只占一部分区域,如果鼠标不在列表上方,滚轮事件不会作用到列表上。把鼠标移到窗口中心,基本就落在列表区域了。

第三部分是去重和写入 txt 的逻辑。我用一个列表 a 存已读到的昵称,用计数器 b 记录数量,用 flag 控制循环退出:

a = [] b = 1 flag = True start_time = time.time() print(f"开始时间:{start_time}") output_file = "wechat_friends.txt" while flag: list_ctrl = comm_admin.ListControl(Name="") first_item = list_ctrl.GetChildren()[0].TextControl() if first_item.Name not in a: print(b, first_item.Name) b += 1 a.append(first_item.Name) with open(output_file, 'a', encoding='utf-8') as f: f.write(first_item.Name + "\n") auto.WheelDown(waitTime=0.01) if auto.IsKeyPressed(auto.Keys.VK_SPACE): print("到底了,开始读取最后一批") for item in list_ctrl.GetChildren()[1:]: last_name = item.TextControl() if last_name.Name not in a: print(b, last_name.Name) b += 1 a.append(last_name.Name) with open(output_file, 'a', encoding='utf-8') as f: f.write(last_name.Name + "\n") flag = False end_time = time.time() print(f"运行时间:{end_time - start_time}s") print(f"共获取 {len(a)} 个好友")

这里写入格式是每行一个昵称,用 \n 换行。如果你想要 CSV 格式,可以改成逗号分隔,但昵称里可能本身有逗号,所以用换行更安全。文件编码用 utf-8,避免中文乱码。

关于去重逻辑,上面用的是if first_item.Name not in a,这会导致同名好友被漏掉。如果你有多个同名好友,建议改成判断是否与最近添加的昵称相同:

if not a or first_item.Name != a[-1]: # 添加逻辑

这样只跳过连续重复的,不会漏掉中间隔开的同名好友。两种方式各有取舍,根据你的好友情况选择。

4. 运行验证与结果落盘检查

脚本写完之后,运行方式很简单:

python wechat_friends.py

运行过程中你会看到控制台不断打印昵称和序号。当滚动到底部时,手动按一下空格键,脚本会读取当前列表里剩余的联系人,然后退出循环。

验证结果是否准确,可以从三个方面检查。第一,看控制台输出的总数和微信通讯录管理页面显示的联系人总数是否一致。微信通讯录管理页面底部会显示总人数,对比一下就知道有没有漏。第二,打开生成的 wechat_friends.txt,检查是否有乱码、空行、重复行。可以用命令行快速统计:

# Windows PowerShell Get-Content wechat_friends.txt | Measure-Object -Line # 或者用 Python 统计 python -c "print(len(open('wechat_friends.txt', encoding='utf-8').readlines()))"

第三,随机抽取几个昵称,在微信里搜索确认是否存在。如果发现漏了,大概率是滚动速度太快导致某些联系人没被渲染出来。可以把auto.WheelDown(waitTime=0.01)里的 waitTime 调大一点,比如 0.05 或 0.1,给微信渲染留出时间。

我实测下来,500 个好友的列表,滚动加读取大概需要 2 到 3 分钟。如果好友数量超过 1000,建议把 waitTime 设成 0.05,否则容易漏。另外,运行脚本期间不要手动操作鼠标和键盘,否则会干扰 uiautomation 的控件定位。

如果你在脚本里集成了 TaoToken 做昵称后处理,比如自动分类或者清洗特殊字符,可以在写入 txt 之前加一步调用:

def clean_nickname(name): # 这里可以调用 TaoToken 的模型接口做清洗 # 简单示例:去掉首尾空格和不可见字符 return name.strip().replace('\u200b', '') # 写入时 f.write(clean_nickname(first_item.Name) + "\n")

模型调用的三件套还是 Base URL https://taotoken.net/api 、API Key 从环境变量读、Model ID 按需选。这样整个流程就是:uiautomation 抓取 → 模型清洗 → 写入 txt,一条龙。

5. 常见报错与排查方法

这一节列几个我踩过的坑,基本都是真实报错。

报错一:AttributeError: 'NoneType' object has no attribute 'Click'

原因:窗口还没加载出来就去找控件,或者 className/Name 写错了。排查方法:在 subprocess.Popen 之后加长 time.sleep,或者用 auto.WindowControl 的 searchDepth 调大一点。也可以用 Inspect.exe 工具查看微信窗口的实际 className 和 Name。

报错二:local proxy failed或连接超时

如果你在脚本里调用了模型接口,出现这个报错通常是网络配置问题。检查 Base URL 是否填的 https://taotoken.net/api ,不要多加路径。如果公司网络有代理,需要在 requests 里配置 proxies 参数,或者设置 NO_PROXY 环境变量。

报错三:401 Unauthorized

API Key 无效或过期。去 TaoToken 控制台重新生成一个,确认复制完整,没有多余空格。环境变量设置后要重开终端才生效。

报错四:reading choices相关错误

模型返回格式不符合预期,通常是 Model ID 填错了。确认你填的 Model ID 在 TaoToken 支持的模型列表里。如果用的是 Claude Code,检查 settings.json 里的 ANTHROPIC_MODEL 字段。

报错五:滚动后列表没有更新

微信的虚拟列表在滚动后需要一点时间渲染。把 WheelDown 的 waitTime 调大,或者在每次滚动后加一个 time.sleep(0.1)。另外确认鼠标确实在列表区域上方,MoveCursorToMyCenter 之后不要再移动鼠标。

报错六:txt 文件中文乱码

打开文件时没有指定 encoding='utf-8'。所有 open() 调用都要加上这个参数。如果已经生成了乱码文件,用记事本打开另存为 UTF-8 编码即可。

报错七:OAuth 相关错误

如果你用的是 Claude Code 的 OAuth 登录方式,而不是 API Key,可能会遇到 token 过期。建议改用 API Key 方式,在 settings.json 里配置 ANTHROPIC_API_KEY 和 ANTHROPIC_BASE_URL,这样更稳定。

排查顺序建议:先确认微信窗口能正常定位,再确认列表控件能读到子元素,最后确认写入文件没有权限问题。每一步都可以用 print 打印中间结果来定位。

6. 凭证管理与脚本调用的后续衔接

好友列表落盘之后,如果你还想做进一步处理,比如按标签分类、按昵称首字母排序、或者调用模型做智能分组,就需要一个稳定的凭证通道。TaoToken 的统一 Key 在这里的价值就体现出来了:你不需要为每个模型单独维护一套 Key,一个 Key 走所有调用。

具体操作路径:先去控制台创建 API Key,地址是 https://taotoken.net/api-keys ,然后参考接入文档 https://taotoken.net/doc 配置你的脚本或工具。如果你用的是 Claude Code 做长期编码任务,可以考虑 Coding Plan https://taotoken.net/coding-plan ,适合需要持续调用模型的场景。如果只是想快速验证某个模型的效果,用模型对话页面 https://taotoken.net/chat 就行。

回到 uiautomation 脚本本身,我建议把凭证读取和好友抓取分成两个模块。抓取模块只负责读控件、写 txt,不关心模型调用;后处理模块从 txt 读数据,调用模型做清洗或分类,再写回新文件。这样职责清晰,调试也方便。

最后给一个实用技巧:如果你的微信好友经常变动,可以把脚本设成每周跑一次,输出文件按日期命名,比如 wechat_friends_20250612.txt。然后在后处理模块里对比两次的差异,就能知道谁新增了、谁删除了。这个用 Python 的 set 差集就能实现,不需要额外工具。

整个流程跑通之后,你会发现 uiautomation 能做的事情远不止抓好友列表。通讯录管理页面里的标签、备注、群聊列表,都可以用类似的方式读取。关键就是找到对应的控件,然后循环读取子元素。多试几次,熟悉了控件树的层级结构,后面就是套模板的事了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询