以下是基于您需求撰写的《微信聊天记录监听与转发工具需求分析开发文档》:
微信聊天记录监听与转发工具
需求分析开发文档
一、项目概述
1.1 目标
开发基于wxauto的自动化工具,实现:
- 实时监听指定微信聊天窗口(群组/个人)
- 捕获并处理新消息
- 按指定策略转发至目标用户"元宝"
- 确保操作间隔符合10秒限制
1.2 技术栈
- 核心框架:Python 3.8+
- 微信自动化:wxauto_custom (基于wxauto的定制版本)
- 并发处理:threading
- 配置管理:configparser
- 数据结构:collections.deque
- 异常处理:logging模块
- 辅助库:random, datetime, os, time
二、核心功能设计
2.1 系统架构
+-----------------------+
| 监听子系统 |
| - 窗口事件监听 |
| - 消息队列管理 |
+----------+------------+
↓
+-----------------------+
| 处理子系统 |
| - 消息过滤 |
| - 内容格式化 |
+----------+------------+
↓
+-----------------------+
| 发送子系统 |
| - 定时调度 |
| - 消息发送 |
+-----------------------+
2.2 功能模块
模块1:窗口监听器 (WindowMonitor)
class WindowMonitor:
def __init__(self, queue, wx_instance):
self.wx = wx_instance # 使用传入的WeChat实例
self.message_queue = queue
self.chats_to_monitor = set(CHATS_TO_MONITOR) # 从配置加载
self.running = False
self._stop_event = threading.Event()
def start_listening(self):
# 启动独立线程进行消息轮询
self.thread = threading.Thread(target=self._poll_messages, daemon=True)
self.thread.start()
def _poll_messages(self):
# 循环调用 GetNextNewMessage 获取新消息
while not self._stop_event.is_set():
aggregated_new_messages = {}
while True:
next_new_msg_dict = self.wx.GetNextNewMessage(savepic=True, savefile=True)
if not next_new_msg_dict:
break
# 处理并聚合消息...
if aggregated_new_messages:
for chat_name, messages_list in aggregated_new_messages.items():
if not self.chats_to_monitor or chat_name in self.chats_to_monitor:
for new_msg in messages_list:
# 将消息放入队列
self.message_queue.append({'chat_name': chat_name, 'message': new_msg})
time.sleep(random.uniform(1.0, 3.0)) # 随机间隔轮询
模块2:消息处理器 (MessageProcessor)
class MessageProcessor:
def __init__(self):
pass # 初始化简单
@ErrorHandler.handle_errors
def process_message(self, raw_msg_data):
# raw_msg_data = {'chat_name': chat_name, 'message': new_msg_object}
raw_msg = raw_msg_data['message']
chat_name = raw_msg_data['chat_name']
# 使用getattr安全访问属性
msg_type = getattr(raw_msg, 'type', 'unknown')
sender = getattr(raw_msg, 'sender', 'Unknown')
content = getattr(raw_msg, 'content', '')
processed = {
'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'sender': sender,
'content': content,
'type': self._detect_content_type(raw_msg), # 检测用于发送的类型
'original_type': msg_type,
'source_chat': chat_name
}
# 提取文件/图片/视频路径
if processed['type'] in ['file', 'image', 'video']:
processed['file_path'] = getattr(raw_msg, 'file', None)
return processed
def _detect_content_type(self, raw_msg):
# 根据原始消息类型和内容判断转发类型 (text, link, image, file, video, emotion)
# ... 实现细节 ...
pass
模块3:消息发送器 (MessageSender)
class MessageSender:
def __init__(self, receiver=RECEIVER, min_interval=MIN_INTERVAL):
self.receiver = receiver
self.min_interval = min_interval # 从配置加载
global last_sent_time
@ErrorHandler.handle_errors
def safe_send(self, message):
global last_sent_time
# 检查发送间隔
now = datetime.datetime.now()
time_since_last_send = (now - last_sent_time).total_seconds()
if time_since_last_send < self.min_interval:
wait_time = self.min_interval - time_since_last_send
time.sleep(wait_time)
try:
# 根据消息类型调用不同发送方法
if message['type'] in ['text', 'link']:
self._send_text(message)
elif message['type'] == 'image':
self._send_image(message) # 使用 _send_image
elif message['type'] == 'file':
self._send_file(message) # 使用 _send_file
elif message['type'] == 'video': # 新增视频处理
self._send_file(message) # 视频也用 SendFiles
elif message['type'] == 'emotion':
self._send_text(message, is_emotion=True)
# ... 其他类型处理 ...
last_sent_time = datetime.datetime.now()
time.sleep(random.uniform(0.5, 1.5)) # 发送后随机暂停
except Exception as e:
logging.error(f"Failed to send message: {str(e)}")
def _send_text(self, msg, is_emotion=False, is_fallback=False):
# 格式化文本消息并发送
formatted = f"[From: {msg.get('source_chat', 'Unknown')}] {msg.get('sender', 'Unknown')}:\n{msg.get('content', '')}"
if is_emotion:
formatted = f"[From: {msg.get('source_chat', 'Unknown')}] {msg.get('sender', 'Unknown')}:\n[表情: {msg.get('content', '')}]"
elif is_fallback:
formatted = f"[From: {msg.get('source_chat', 'Unknown')}] {msg.get('sender', 'Unknown')}:\n{msg.get('content', '[Content could not be forwarded]')}"
wx.SendMsg(formatted, self.receiver) # 使用 SendMsg
def _send_image(self, msg):
# 发送图片文件
file_path = msg.get('file_path')
if file_path and os.path.exists(file_path):
wx.SendFiles([file_path], self.receiver) # 使用 SendFiles
else:
self._send_text({'content': '[Image could not be forwarded]', **msg}, is_fallback=True)
def _send_file(self, msg):
# 发送普通文件或视频文件
file_path = msg.get('file_path')
if file_path and os.path.exists(file_path):
wx.SendFiles([file_path], self.receiver) # 使用 SendFiles
else:
self._send_text({'content': '[File could not be forwarded]', **msg}, is_fallback=True)
2.3 调度器 (Scheduler)
class Scheduler:
def __init__(self, queue, processor, sender):
self.message_queue = queue
self.processor = processor
self.sender = sender
self.running = False
self._stop_event = threading.Event()
def start(self):
# 启动独立线程处理和发送消息
self.thread = threading.Thread(target=self._run, daemon=True)
self.thread.start()
def _run(self):
while not self._stop_event.is_set():
if not self.message_queue:
self._stop_event.wait(1.0) # 队列为空时等待
continue
raw_msg = self.message_queue.popleft()
processed_msg = self.processor.process_message(raw_msg)
if processed_msg:
self.sender.safe_send(processed_msg)
# 短暂休眠避免CPU空转 (实际代码在WindowMonitor轮询处休眠)
三、关键技术实现
3.1 消息类型处理与转发
消息类型 (原始) | 处理方式 (转发) | 发送方法 (wxauto_custom) |
---|---|---|
text | 拼接来源和发送者信息 | wx.SendMsg |
link | 拼接来源和发送者信息 (同text) | wx.SendMsg |
image | 获取本地路径后发送文件 | wx.SendFiles |
file | 获取本地路径后发送文件 | wx.SendFiles |
video | 获取本地路径后发送文件 | wx.SendFiles |
emotion | 发送 [表情: 内容] 文本 | wx.SendMsg |
其他 | 默认按文本处理或忽略 | wx.SendMsg (可能) |
3.2 异常处理机制
class ErrorHandler:
@staticmethod
def handle_errors(func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
# 移除了对 wxauto 特定异常的处理 (WindowNotFoundException, MessageSendTimeout)
# 因为它们在 wxauto_custom.errors 中可能不存在或已更改
except Exception as e:
# 使用 logging 记录未处理的通用异常
logging.critical(f"Unhandled exception in {func.__name__}: {str(e)}", exc_info=True)
return wrapper
四、部署与使用
4.1 环境要求
# 核心依赖 (请根据实际使用的 wxauto_custom 版本调整)
# pip install wxauto_custom # 假设库名为 wxauto_custom
# 或者如果直接修改了 wxauto 库,则安装原版
# pip install wxauto==<version_used_by_custom>
# 其他标准库 (通常随 Python 安装)
# configparser, logging, threading, collections, random, datetime, os, time
注意: wxauto
或其定制版通常对微信客户端版本有要求,请参考库文档确认兼容性。
4.2 配置文件示例 (config.ini)
[target]
receiver = 元宝
interval = 10
chats_to_monitor = 测试群1, HR
五、注意事项
- 微信版本限制:需使用官方客户端v3.7.6以下版本
- 窗口焦点要求:需保持微信窗口处于前台运行状态
- 防检测机制:轮询和发送后加入随机延时,模拟人类行为
- 性能优化:建议关闭无关聊天窗口降低资源占用
六、测试方案
测试用例矩阵
测试场景 | 输入类型 | 预期结果 |
---|---|---|
群文本消息 | 文字 | 正确转发带来源信息 |
私聊图片 | JPEG | 成功发送图片文件 |
连续消息发送 | 多条文本 | 间隔不小于配置的 interval 值 |
微信窗口最小化 | - | 可能无法正常捕获 (依赖UI自动化) |
网络中断 | - | 错误重试机制正常触发 |