基于WeChatFerry的微信机器人开发:从原理到实战应用
1. 项目概述:为什么选择WeChatFerry?
最近在折腾自动化流程,发现很多重复性的微信消息处理和群管理任务特别耗费时间。市面上虽然有一些基于Web协议的微信机器人方案,但要么是协议不稳定容易被封,要么是功能受限,开发起来也颇为复杂。直到我发现了WeChatFerry这个框架,它提供了一种相对稳定、功能强大且易于上手的解决方案,让我能够快速构建自己的微信自动化工具。
简单来说,WeChatFerry是一个基于PC版微信客户端的自动化框架。它不依赖于容易被封禁的Web协议,而是通过进程注入和内存操作的方式,直接与微信客户端进行交互。这意味着它的功能可以非常接近甚至等同于人工操作,比如发送消息、接收消息、管理好友和群聊、获取通讯录等。对于需要处理大量微信消息、进行社群运营、或是构建自动化客服系统的开发者来说,这是一个非常实用的工具。
本指南旨在为刚接触WeChatFerry的朋友提供一个清晰的入门路径。我不会只停留在“Hello World”的层面,而是会带你从环境搭建开始,一步步实现一个具备实用功能的机器人,并分享我在实战中踩过的坑和积累的经验。无论你是想写一个自动回复的聊天机器人,还是想构建一个复杂的社群管理工具,相信这篇指南都能给你带来帮助。
2. 核心思路与方案选型解析
在开始敲代码之前,我们先来理清思路:我们到底要做一个什么样的机器人?以及,为什么WeChatFerry是当前阶段一个不错的选择?
2.1 微信机器人方案的横向对比
市面上实现微信机器人的主流方案大致有三种:
基于Web协议的方案:例如itchat、wxpy(已停止维护)等。它们通过模拟网页版微信登录,调用其API。优点是纯Python,上手快。但致命缺点是,微信官方早已加强了对网页版的管控,此类方案极不稳定,登录困难,且非常容易被封号,目前已基本不可用于生产环境。
基于安卓协议(Xposed/模块)的方案:在安卓手机上通过Xposed框架或Magisk模块注入,直接Hook微信App的函数调用。功能强大且相对稳定,但技术门槛高,需要逆向分析,且严重依赖特定版本的微信App,一旦微信更新,模块可能失效。环境搭建也较为复杂。
基于PC客户端注入的方案:这正是WeChatFerry所采用的路径。它通过向PC版微信进程注入一个DLL(动态链接库),这个DLL能够直接调用微信客户端内部未公开的函数,从而实现各种自动化操作。其优势在于:
- 功能全面:由于是直接操作客户端,理论上人工能在PC微信上做的操作,它都能模拟。
- 相对稳定:PC客户端的协议变更频率远低于移动端和网页端,因此框架的生命周期更长。
- 性能与资源:运行在PC上,可以方便地利用电脑的计算资源和存储,集成其他服务(如数据库、AI模型)也更简单。
- 规避账号风险:操作行为更接近真人(因为就是在真客户端上操作),理论上比频繁调用不明API的Web方案更安全。
综合来看,对于希望在Windows环境下快速开发、需要稳定且功能丰富的微信自动化应用的开发者,WeChatFerry是目前一个非常值得投入学习的框架。
2.2 WeChatFerry的工作原理浅析
理解其工作原理,有助于我们在开发时避开一些雷区。WeChatFerry的核心是一个“桥梁(Ferry)”。
- 注入器(Injector):首先,一个独立的程序(通常是C++编写)会将一个自定义的DLL文件注入到正在运行的微信进程的内存空间中。这个DLL就像是潜伏在微信内部的一个“间谍”。
- RPC服务:被注入的DLL会启动一个RPC(远程过程调用)服务器,并监听一个本地端口(例如
18080)。这个服务器暴露了一系列函数接口,对应着微信的各种功能,如SendTextMsg(发送文本消息)。 - 客户端SDK:我们的Python(或其他语言)程序,作为RPC客户端,通过HTTP或WebSocket协议连接到这个本地端口。然后,通过调用SDK封装好的方法,向RPC服务器发送指令。
- 指令执行:RPC服务器收到指令后,由DLL内部代码直接调用微信客户端的原生函数,完成相应操作,并将结果返回给我们的Python程序。
整个过程,我们的Python代码并没有直接“控制”微信,而是通过一个“中间人”(RPC服务)来间接操作。这种设计解耦了控制逻辑和底层注入模块,使得SDK可以独立更新,也更加安全。
注意:进程注入技术本身可能会被安全软件误报为病毒或恶意行为。在开发和运行WeChatFerry相关程序时,需要将相关目录添加到安全软件的信任区,或暂时关闭实时防护。
3. 环境搭建与核心工具准备
工欲善其事,必先利其器。下面我们来一步步搭建WeChatFerry的开发环境。我假设你使用的是Windows 10/11系统,并且已经安装了Python。
3.1 基础环境配置
首先,确保你的PC上已经安装了PC版微信。建议从微信官网下载并安装最新稳定版。WeChatFerry通常会对主流版本进行适配。
接下来是Python环境。我强烈建议使用conda或venv创建独立的虚拟环境,避免包依赖冲突。
# 使用conda创建环境(如果你安装了Anaconda或Miniconda) conda create -n wechatferry python=3.8 conda activate wechatferry # 或者使用Python内置的venv python -m venv wechatferry_env # Windows下激活 wechatferry_env\Scripts\activate3.2 安装WeChatFerry SDK
WeChatFerry的Python SDK可以通过pip直接安装。它是我们编写机器人逻辑的主要工具。
pip install wechatferry安装完成后,可以尝试在Python交互环境中导入,确认安装成功:
import wechatferry print(wechatferry.__version__)3.3 获取并配置Ferry核心组件
SDK只是客户端,我们还需要服务端,也就是那个要注入到微信里的核心组件。这个组件通常以WeChatFerry.dll和Injector.exe的形式提供。
- 获取组件:你需要从WeChatFerry项目的GitHub Releases页面或其他官方指定的渠道,下载对应你微信版本和系统位数的压缩包(例如
WeChatFerry-vx.x.x-win64.zip)。 - 解压:将压缩包解压到一个你喜欢的目录,例如
D:\Tools\WeChatFerry。记住这个路径。 - 目录结构:解压后,你通常会看到类似以下文件:
Injector.exe: 注入器主程序。WeChatFerry.dll: 核心功能DLL。config.toml: 配置文件(可能没有,需要自己创建或由注入器生成)。README.md: 说明文件。
3.4 启动与连接测试
这是最关键的一步,将Ferry服务注入到微信中。
- 登录微信:首先,确保你的PC版微信已经正常登录。
- 运行注入器:以管理员身份运行
Injector.exe。这是必须的,因为进程注入需要较高的权限。 - 观察日志:运行后,控制台窗口会输出日志。如果看到类似
[INFO] Inject成功,PID: xxxx, 监听端口: 18080的信息,说明注入成功。同时,你的微信窗口标题栏可能会多出一个[Ferry]的标识。 - Python连接测试:新建一个Python脚本,编写以下代码进行连接测试。
# test_connection.py from wechatferry import WeChatFerry # 创建客户端实例,默认连接本地18080端口 client = WeChatFerry(host='127.0.0.1', port=18080, timeout=15) # 尝试获取登录微信的账号信息,用于测试连接 self_info = client.get_self_info() if self_info: print(f"连接成功!当前登录账号:{self_info.get('wxid')} - {self_info.get('nickname')}") else: print("连接失败,请检查Ferry服务是否已启动。")如果运行后能成功打印出你的微信昵称和ID,那么恭喜你,环境搭建全部完成!如果失败,请检查:
- 是否以管理员身份运行了Injector?
- 微信是否已登录?
- 防火墙是否阻止了本地端口
18080的通信? - Python脚本中的端口号是否与Injector输出的端口号一致?
4. 核心功能实战:打造你的第一个机器人
环境通了,我们就可以开始实现功能了。让我们从一个最简单的“回声机器人”开始,然后逐步增加实用功能。
4.1 消息接收与处理
机器人的核心是响应消息。WeChatFerry通过回调机制来接收消息。
# echo_bot.py import time from wechatferry import WeChatFerry, WxMsg # 初始化客户端 client = WeChatFerry(host='127.0.0.1', port=18080) # 定义一个消息处理函数 def on_message(msg: WxMsg): """收到任何消息后的回调函数""" print(f"[收到消息] 来自: {msg.sender}({msg.room_wxid if msg.is_room else '私聊'}), 内容: {msg.content}") # 实现“回声”功能:如果是私聊文本消息,就原样发回去 if not msg.is_room and msg.type == 1: # 类型1通常代表文本消息 # 注意:直接回复可能会造成死循环(机器人发消息也会触发回调),这里加个简单判断 # 可以通过消息发送者是否是机器人自己来判断,这里我们用内容前缀判断作为示例 if not msg.content.startswith("[Bot Echo]:"): reply_content = f"[Bot Echo]: {msg.content}" client.send_text(msg.sender, reply_content) print(f"[已回复] {reply_content}") # 注册消息回调函数 client.on_message = on_message print("回声机器人已启动,按 Ctrl+C 停止...") try: # 保持主线程运行,以便持续接收回调 while True: time.sleep(1) except KeyboardInterrupt: print("\n机器人已停止。") client.close()代码解析与注意事项:
WxMsg对象包含了消息的所有信息:发送者(sender)、接收者(receiver)、内容(content)、类型(type)、是否为群消息(is_room)等。client.on_message是一个属性,你可以直接赋值为你的处理函数。当有新消息时,框架会自动调用它。- 死循环风险:在上面的例子中,如果机器人A发送了消息,这个消息也会被
on_message回调捕获。如果处理逻辑不加判断地再次调用send_text,就会导致机器人自己给自己发消息,循环往复。因此,必须在处理逻辑中加入防循环判断。常见的策略有:- 判断发送者WxId是否等于机器人自己的WxId。
- 在回复的消息内容中添加特殊标记(如
[Bot]),并在回调中忽略带有此标记的消息。 - 使用一个简单的内存集合记录最近已处理的消息ID,避免重复处理。
- 消息类型(
type)需要查阅WeChatFerry的文档或源码来确认,常见的如1(文本)、3(图片)、34(语音)、47(表情)、49(链接/文件/小程序等)。
4.2 消息发送详解
发送消息是机器人主动交互的基础。除了文本,还能发送图片、文件、甚至@群成员。
# message_sender.py from wechatferry import WeChatFerry import os client = WeChatFerry() # 1. 发送纯文本消息 # 参数:接收者wxid, 消息内容 client.send_text('filehelper', '这是一条测试消息,发送给文件传输助手。') # 2. 发送图片消息 # 参数:接收者wxid, 本地图片文件路径 image_path = r'C:\Users\YourName\Pictures\test.png' if os.path.exists(image_path): client.send_image('filehelper', image_path) else: print(f"图片文件不存在: {image_path}") # 3. 发送文件 # 参数:接收者wxid, 本地文件路径 file_path = r'C:\Users\YourName\Documents\report.pdf' if os.path.exists(file_path): client.send_file('filehelper', file_path) # 4. 在群聊中发送消息并@特定成员 # 首先,需要获取群的wxid和要@的成员的wxid(如何获取后面会讲) group_wxid = '123456789@chatroom' # 示例群ID at_member_wxid = 'wxid_xxxxxxxxxxxxx' # 示例成员ID # 构造@消息的格式:@昵称 + 实际消息内容 # 注意:这里的特殊空格是`\u2005`,不是普通空格。Ferry的SDK可能提供了工具函数。 # 一种常见格式是:`@昵称\u2005消息内容` # 更可靠的方式是使用SDK的`send_text`并指定`at_list`参数(如果SDK支持)。 # 假设SDK支持at_list(请以实际SDK文档为准): at_list = [at_member_wxid] client.send_text(group_wxid, '请查收一下这份资料。', at_list=at_list) # 如果不支持at_list,则需要手动拼接XML格式的@消息,这比较复杂,依赖于微信内部格式。实操心得:
- 接收者WxId:这是最关键的信息。私聊的WxId通常是
wxid_开头的字符串,而群聊的WxId是以@chatroom结尾的字符串。filehelper是一个特殊的WxId,代表“文件传输助手”,常用于测试。 - 文件路径:务必使用原始字符串(
r'...')或双反斜杠(\\)来表示Windows路径,避免转义字符出错。 - @功能的复杂性:群内@功能涉及到微信内部的消息格式(可能是XML)。不同版本的WeChatFerry SDK对此封装程度不同。务必查阅你所用版本的官方文档或源码,寻找是否有像
send_at_text或send_text的at_list参数这样的封装方法。手动拼接XML极易出错且不稳定。 - 速度限制:不要以极高的频率发送消息,模拟人类操作间隔,避免被微信限制功能。
4.3 获取通讯录与群成员列表
一个智能的机器人需要知道它在和谁对话。WeChatFerry提供了获取联系人信息的接口。
# contact_manager.py from wechatferry import WeChatFerry import json client = WeChatFerry() # 1. 获取登录账号自身信息 self_info = client.get_self_info() print("自身信息:", json.dumps(self_info, indent=2, ensure_ascii=False)) # 2. 获取所有好友列表(通讯录) # 注意:此操作可能较慢,返回数据量大 all_contacts = client.get_contacts() print(f"好友总数: {len(all_contacts)}") # 打印前几个好友看看 for i, contact in enumerate(all_contacts[:5]): print(f"{i+1}. 昵称: {contact.get('nickname')}, WxId: {contact.get('wxid')}, 备注: {contact.get('remark')}") # 3. 获取所有群聊列表 all_chatrooms = client.get_chatrooms() print(f"\n群聊总数: {len(all_chatrooms)}") for i, room in enumerate(all_chatrooms[:5]): print(f"{i+1}. 群名: {room.get('nickname')}, RoomId: {room.get('wxid')}") # 4. 获取特定群聊的成员详情 # 首先需要一个群的wxid if all_chatrooms: target_room_id = all_chatrooms[0]['wxid'] # 取第一个群 room_members = client.get_chatroom_members(target_room_id) print(f"\n群【{all_chatrooms[0].get('nickname')}】的成员列表:") for member in room_members: # 成员信息中可能包含昵称、wxid、群昵称(displayname)等 display_name = member.get('displayname') or member.get('nickname') print(f" - {display_name} ({member.get('wxid')})")注意事项:
- 性能与缓存:
get_contacts()和get_chatrooms()获取的是完整列表,数据量可能很大,不宜频繁调用。在实际项目中,可以考虑在程序启动时获取一次并缓存起来,定时更新。 - 信息字段:不同版本的WeChatFerry返回的联系人信息字段可能略有差异。常见的字段有
wxid(唯一标识)、nickname(微信昵称)、remark(你设置的备注)、alias(微信号)。群成员还可能有displayname(在群里的昵称)。 - WxId的稳定性:好友的
wxid通常是稳定的,但群成员的wxid在同一个群内是稳定的,不同群之间可能不同(微信的机制)。所以不能直接用A群获取的成员wxid去B群里@他。
4.4 实现一个实用的关键词回复机器人
结合以上知识,我们可以做一个更有用的机器人:在群聊中监听特定关键词(如“#天气 北京”),并调用外部API获取信息后回复。
# keyword_bot.py import time import requests from wechatferry import WeChatFerry, WxMsg client = WeChatFerry() # 假设的天气API函数 def get_weather(city): # 这里使用一个示例API,实际使用时请替换为真实的天气API(如和风、心知等) # 并处理好API Key和请求频率限制 try: # 示例:模拟请求 # response = requests.get(f'https://api.weather.com/...?city={city}') # data = response.json() # return data['weather'] return f"{city}的天气是晴朗,25℃。" # 模拟返回 except Exception as e: return f"获取天气失败:{e}" def on_message(msg: WxMsg): # 只处理群文本消息 if not msg.is_room or msg.type != 1: return content = msg.content.strip() sender = msg.sender # 消息发送者的wxid room_wxid = msg.room_wxid # 群聊的wxid # 判断是否为触发命令,例如以“#天气”开头 if content.startswith('#天气'): # 提取城市名,命令格式如“#天气 北京” parts = content.split() if len(parts) < 2: reply = "请输入正确的格式:#天气 城市名" else: city = parts[1] weather_info = get_weather(city) reply = f"@{msg.sender_name} {weather_info}" # 假设msg对象有sender_name属性,实际可能需要从缓存中查询 # 更稳妥的方式:先获取发送者在群里的显示名 # 这里简化处理,直接回复文本 reply = f"{weather_info}" # 发送回复到群里 client.send_text(room_wxid, reply) print(f"[群{room_wxid}] 响应命令: {content} -> {reply}") # 可以添加更多关键词判断 elif content == '#帮助': help_text = "可用命令:\\n#天气 城市 - 查询天气\\n#帮助 - 显示此帮助" client.send_text(room_wxid, help_text) client.on_message = on_message print("关键词回复机器人已启动...") try: while True: time.sleep(1) except KeyboardInterrupt: client.close()功能扩展思路:
- 接入AI:将
content发送给像OpenAI API、文心一言、通义千问等大语言模型,让机器人进行智能对话。 - 定时任务:结合Python的
schedule或apscheduler库,实现定时向某个群发送新闻摘要、每日提醒等。 - 消息转发:将特定群或人的消息转发到另一个群(如工作通知转发到个人微信)、邮件或Webhook,实现通知聚合。
- 数据记录:将所有消息存储到数据库(如SQLite、MySQL),用于后续分析或审计。
5. 工程化与高级技巧
当你的机器人功能越来越复杂时,就需要考虑代码结构、稳定性和可维护性了。
5.1 项目结构组织
一个简单的工程化目录结构可以这样安排:
my_wechat_bot/ ├── bot.py # 主程序入口,负责初始化、启动、关闭 ├── config.py # 配置文件(API密钥、监听群列表等) ├── core/ │ ├── __init__.py │ ├── ferry_client.py # 封装WeChatFerry客户端,提供单例和重连逻辑 │ └── message_handler.py # 核心消息处理分发器 ├── handlers/ # 各种消息处理器 │ ├── __init__.py │ ├── echo_handler.py │ ├── weather_handler.py │ └── admin_handler.py # 管理命令处理器 ├── utils/ # 工具函数 │ ├── __init__.py │ ├── logger.py # 日志配置 │ └── cache.py # 联系人缓存 └── requirements.txt # 项目依赖在message_handler.py中,可以实现一个分发器,根据消息类型、内容关键词等,将消息路由到不同的handler进行处理,避免on_message回调函数变得无比臃肿。
5.2 连接稳定性与重连机制
网络波动或微信客户端重启都可能导致Ferry连接断开。一个健壮的机器人必须具备重连能力。
# core/ferry_client.py import time import logging from wechatferry import WeChatFerry logger = logging.getLogger(__name__) class FerryManager: def __init__(self, host='127.0.0.1', port=18080): self.host = host self.port = port self.client = None self.max_retries = 5 self.retry_interval = 10 # 秒 def connect(self): """连接Ferry服务,支持重试""" for attempt in range(self.max_retries): try: logger.info(f"尝试连接Ferry服务 (尝试 {attempt + 1}/{self.max_retries})...") self.client = WeChatFerry(host=self.host, port=self.port, timeout=30) # 做一个简单的测试调用验证连接 self.client.get_self_info() logger.info("Ferry服务连接成功!") return True except Exception as e: logger.error(f"连接失败: {e}") if attempt < self.max_retries - 1: logger.info(f"{self.retry_interval}秒后重试...") time.sleep(self.retry_interval) else: logger.critical("达到最大重试次数,连接失败。") return False def ensure_connection(self): """确保连接有效,如果断开则尝试重连""" if self.client is None: return self.connect() try: # 发送一个无害的指令来检测连接是否存活 self.client.get_self_info() return True except Exception: logger.warning("连接似乎已断开,尝试重新连接...") self.client = None return self.connect() def get_client(self): """获取客户端实例,确保连接有效""" if self.ensure_connection(): return self.client else: raise ConnectionError("无法建立到Ferry服务的连接。")在主程序中,你可以定期(例如每小时)调用ensure_connection来检查连接状态,或者在每次发送消息前调用get_client()来获取一个确保可用的客户端。
5.3 日志记录与问题排查
良好的日志是排查问题的生命线。建议使用Python标准库的logging模块。
# utils/logger.py import logging import sys from logging.handlers import RotatingFileHandler def setup_logger(name, log_file='bot.log', level=logging.INFO): """设置日志记录器""" logger = logging.getLogger(name) logger.setLevel(level) # 避免重复添加handler if logger.handlers: return logger # 格式 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 控制台输出 console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(formatter) logger.addHandler(console_handler) # 文件输出(按大小滚动) file_handler = RotatingFileHandler( log_file, maxBytes=10*1024*1024, backupCount=5 # 10MB一个文件,保留5个 ) file_handler.setFormatter(formatter) logger.addHandler(file_handler) return logger # 在项目中使用 # core/ferry_client.py logger = setup_logger('ferry') # handlers/weather_handler.py logger = setup_logger('weather')在关键节点(连接成功/失败、收到消息、发送消息、调用API)记录不同级别的日志(INFO, WARNING, ERROR),这样当机器人行为异常时,你可以通过查看bot.log文件快速定位问题发生的时间点和上下文。
6. 常见问题与避坑指南实录
在实际开发和运行过程中,我遇到了不少问题。这里总结一些典型场景和解决方案,希望能帮你节省时间。
6.1 连接与注入问题
问题:
Injector.exe运行后一闪而过,或提示“注入失败”。- 排查1:权限问题。必须以管理员身份运行
Injector.exe。右键点击,选择“以管理员身份运行”。 - 排查2:微信客户端版本不匹配。确保你下载的
WeChatFerry.dll版本支持你当前安装的微信版本。去项目发布页面查看版本说明。 - 排查3:安全软件拦截。暂时关闭Windows Defender实时保护或其他第三方杀毒软件,或将
Injector.exe和WeChatFerry.dll所在目录添加到信任区。 - 排查4:端口占用。默认端口
18080可能被其他程序占用。可以尝试修改config.toml(如果存在)或注入器参数来更换端口,并在Python代码中相应修改。
- 排查1:权限问题。必须以管理员身份运行
问题:Python脚本连接超时(
Connection refused或Timeout)。- 排查1:Ferry服务未启动。确认
Injector.exe已成功运行并输出“Inject成功”的日志。 - 排查2:端口号不一致。检查
Injector.exe输出日志中监听的端口号(如监听端口: 18081),确保Python脚本中WeChatFerry(port=...)的参数与之相同。 - 排查3:防火墙阻止。确保Windows防火墙允许本地程序在
127.0.0.1的指定端口上进行通信。
- 排查1:Ferry服务未启动。确认
6.2 消息收发异常
问题:机器人能收到消息,但发送消息失败或无反应。
- 排查1:接收者WxId错误。这是最常见的原因。特别是群ID,必须是以
@chatroom结尾的完整ID。使用get_chatrooms()函数获取准确的群ID列表。 - 排查2:消息内容格式。发送特殊内容(如包含换行符、特定表情符号)时可能会失败。尝试发送最简单的纯文本测试。
- 排查3:发送频率过高。微信对消息发送频率有限制。在循环中发送消息时,务必在每次发送之间添加
time.sleep(1)或更长的间隔。 - 排查4:微信客户端焦点。某些版本的注入方式可能要求微信窗口处于非最小化状态(即进程在后台活跃即可,不一定需要前台)。确保微信在运行,不要关闭主窗口。
- 排查1:接收者WxId错误。这是最常见的原因。特别是群ID,必须是以
问题:在群聊中@某人失败,或者@变成了纯文本。
- 原因:如前所述,@功能需要特定的消息格式。绝对不要自己拼接
@昵称后面加空格和内容。 - 解决:仔细阅读你所使用的WeChatFerry SDK版本的文档或源码,寻找官方提供的@方法。例如,可能是一个独立的
send_at_msg函数,或者是send_text函数的一个at_list参数。如果官方未提供,此功能可能在该版本尚未实现或实现不稳定,建议降级或升级SDK版本,或在社区寻求帮助。
- 原因:如前所述,@功能需要特定的消息格式。绝对不要自己拼接
6.3 资源管理与性能
问题:运行一段时间后,程序内存占用越来越高,或者响应变慢。
- 排查1:消息回调中的阻塞操作。如果在
on_message回调函数中执行了耗时的操作(如网络请求、复杂计算),会阻塞后续消息的处理。务必使用异步或多线程。 - 解决:将耗时操作放入线程池或使用
asyncio。例如:import threading from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(max_workers=5) def on_message(msg: WxMsg): # 快速判断,不耗时 if is_need_process(msg): # 将耗时任务提交到线程池 executor.submit(process_message_heavy_task, msg) - 排查2:未及时清理缓存。如果你缓存了通讯录等数据,并持续向缓存中添加条目,可能导致内存泄漏。为缓存设置大小限制或过期时间。
- 排查3:日志文件无限增长。使用
RotatingFileHandler(如上文示例)来限制单个日志文件大小和数量。
- 排查1:消息回调中的阻塞操作。如果在
问题:如何让机器人24小时稳定运行?
- 方案1:使用进程守护。在Windows上,可以编写一个简单的
.bat脚本或使用nssm(Non-Sucking Service Manager)将你的Python脚本注册为系统服务,实现开机自启和崩溃重启。 - 方案2:容器化部署。虽然WeChatFerry依赖Windows和微信客户端,使得容器化困难,但你可以在一台专用的Windows服务器或虚拟机上运行,并使用任务计划程序来监控和重启你的机器人脚本。
- 核心:结合5.2节的重连机制和完善的日志记录,确保在出现可恢复的错误时,机器人能自动恢复。
- 方案1:使用进程守护。在Windows上,可以编写一个简单的
6.4 其他实用技巧
- 如何找到“文件传输助手”的WxId?它通常是固定的
filehelper。你也可以通过get_contacts()列表查找昵称为“文件传输助手”的联系人。 - 如何获取自己在群里的显示名?通过
get_chatroom_members(room_wxid)获取群成员列表,然后查找wxid与自身WxId(通过get_self_info()获取)匹配的成员,其displayname或nickname即为你在该群的显示名。 - 消息类型判断:除了
msg.type,WxMsg对象可能还有其他属性如is_text,is_image,is_link等(取决于SDK版本),用这些属性判断比用数字更可读。 - 处理表情和图片:接收到的图片、文件等消息,其内容(
msg.content)可能是一个XML字符串或本地缓存路径。你需要解析这个字符串或根据路径去微信的缓存目录查找文件。这部分比较复杂,建议参考SDK中处理多媒体消息的示例代码。
最后,保持关注WeChatFerry项目的官方仓库和社区,框架和微信客户端都在更新,及时跟进新版本能获得更好的兼容性和新功能。开发这类工具,耐心和动手调试能力是关键,多看看日志,多写测试代码,你的机器人一定会越来越聪明可靠。
