wxauto源码解读:wxauto.py中的核心类与方法设计

wxauto源码解读:wxauto.py中的核心类与方法设计

【免费下载链接】wxauto Windows版本微信客户端(非网页版)自动化,可实现简单的发送、接收微信消息,简单微信机器人 【免费下载链接】wxauto 项目地址: https://gitcode.com/gh_mirrors/wx/wxauto

引言:为什么wxauto.py是微信自动化的核心

在Windows平台的微信客户端自动化领域,wxauto项目提供了一套简洁而强大的解决方案。本文将深入剖析其核心文件wxauto.py的架构设计与实现细节,揭示如何通过UI自动化技术实现对微信客户端的精准控制。通过本文,你将获得:

  • 对WeChat类核心架构的深度理解
  • 消息处理机制的完整工作流程
  • 自动化控制的关键技术实现
  • 实用功能的代码级解析

WeChat类架构:微信自动化的基石

类继承关系与核心属性

WeChat类作为整个自动化框架的入口点,继承自WeChatBase基类,实现了对微信主窗口的全面控制。其核心架构如下:

mermaid

WeChat类初始化时会建立与微信主窗口的连接,并完成三大核心区域的布局解析:

# 三个布局,导航栏(A)、聊天列表(B)、聊天框(C)
# _______________
# |■|———|    -□×|
# | |———|       |
# |A| B |   C   |   <--- 微信窗口布局简图示意
# | |———|———————|
# |=|———|       |
# ———————————————
self.NavigationBox, self.SessionBox, self.ChatBox  = MainControl2.GetChildren()

多语言支持机制

为实现国际化支持,WeChat类采用了灵活的语言切换机制:

def __init__(
        self, 
        language: Literal['cn', 'cn_t', 'en'] = 'cn', 
        debug: bool = False
    ) -> None:
    """微信UI自动化实例

    Args:
        language (str, optional): 微信客户端语言版本, 可选: cn简体中文  cn_t繁体中文  en英文, 默认cn, 即简体中文
    """
    set_debug(debug)
    self.language = language
    # ...其他初始化代码

通过_lang()方法实现多语言文本的动态切换:

def _lang(self, text, langtype='MAIN'):
    if langtype == 'MAIN':
        return MAIN_LANGUAGE[text][self.language]
    elif langtype == 'WARNING':
        return WARNING[text][self.language]

消息处理机制:从接收 to 响应

消息获取流程

WeChat类实现了完整的消息监听与获取机制,其核心流程如下:

mermaid

关键实现代码在GetNextNewMessage()方法中:

def GetNextNewMessage(self, savepic=False, savefile=False, savevoice=False, timeout=10):
    """获取下一个新消息"""
    msgs_ = self.GetAllMessage()
    msgids = [i[-1] for i in msgs_]

    if not self.usedmsgid:
        self.usedmsgid = msgids
    
    newmsgids = [i for i in msgids if i not in self.usedmsgid]
    oldmsgids = [i for i in self.usedmsgid if i in msgids]
    
    # ...消息提取与处理逻辑...
    
    return {session:msgs}

消息类型处理

系统能够识别并处理多种消息类型,包括文本、图片、文件和语音:

def _getmsgs(self, msgitems, savepic=False, savefile=False, savevoice=False):
    msgs = []
    for MsgItem in msgitems:
        if MsgItem.ControlTypeName == 'ListItemControl':
            msgs.append(self._split(MsgItem))

    # ...特殊消息处理逻辑...
    
    for msg in msgs:
        if msg.type not in ('friend', 'self'):
            continue
        if msg.content.startswith(f"[{self._lang('图片')}]") and savepic:
            imgpath = self._download_pic(msg.control)
            msg.content = imgpath if imgpath else msg.content
        elif msg.content.startswith(f"[{self._lang('文件')}]") and savefile:
            filepath = self._download_file(msg.control)
            msg.content = filepath if filepath else msg.content
        elif msg.content.startswith(f"[{self._lang('语音')}]") and savevoice:
            voice_text = self._get_voice_text(msg.control)
            msg.content = voice_text if voice_text else msg.content
    return msgs

核心功能实现详解

1. 聊天窗口控制

ChatWith()方法实现了精准定位并打开指定聊天窗口的功能,支持通过名称搜索和直接访问两种模式:

def ChatWith(self, who, timeout=2):
    '''打开某个聊天框
    
    Args:
        who ( str ): 要打开的聊天框好友名;  * 最好完整匹配,不完全匹配只会选取搜索框第一个
        timeout ( num, optional ): 超时时间,默认2秒
        
    Returns:
        chatname ( str ): 匹配值第一个的完整名字
    '''
    self._show()
    sessiondict = self.GetSessionList(True)
    if who in list(sessiondict.keys())[:-1]:
        self.SessionBox.ListItemControl(RegexName=who).Click(simulateMove=False)
        return who
    else:
        # ...搜索逻辑实现...

2. 消息发送系统

SendMsg()方法支持文本消息发送,并提供@功能:

def SendMsg(self, msg, who=None, clear=True, at=None):
    """发送文本消息

    Args:
        msg (str): 要发送的文本消息
        who (str): 要发送给谁,如果为None,则发送到当前聊天页面。  *最好完整匹配,优先使用备注
        clear (bool, optional): 是否清除原本的内容,
        at (str|list, optional): 要@的人,可以是一个人或多个人
    """
    # ...前置检查逻辑...
    
    if at:
        if isinstance(at, str):
            at = [at]
        for i in at:
            editbox.SendKeys('@'+i)
            atwnd = self.UiaAPI.PaneControl(ClassName='ChatContactMenu')
            if atwnd.Exists(maxSearchSeconds=0.1):
                atwnd.SendKeys('{ENTER}')
                if msg and not msg.startswith('\n'):
                    msg = '\n' + msg

    # ...消息发送逻辑...

3. 监听功能实现

通过AddListenChat()GetListenMessage()方法组合,实现对指定聊天的持续监听:

def AddListenChat(self, who, savepic=False, savefile=False, savevoice=False):
    """添加监听对象"""
    exists = uia.WindowControl(searchDepth=1, ClassName='ChatWnd', Name=who).Exists(maxSearchSeconds=0.1)
    if not exists:
        self.ChatWith(who)
        self.SessionBox.ListItemControl(RegexName=who).DoubleClick(simulateMove=False)
    self.listen[who] = ChatWnd(who, self.language)
    self.listen[who].savepic = savepic
    self.listen[who].savefile = savefile
    self.listen[who].savevoice = savevoice

监听状态通过字典维护,可同时监控多个聊天对象:

def GetListenMessage(self, who=None):
    """获取监听对象的新消息"""
    if who and who in self.listen:
        chat = self.listen[who]
        msg = chat.GetNewMessage(savepic=chat.savepic, savefile=chat.savefile, savevoice=chat.savevoice)
        return msg
    msgs = {}
    for who in self.listen:
        chat = self.listen[who]
        msg = chat.GetNewMessage(savepic=chat.savepic, savefile=chat.savefile, savevoice=chat.savevoice)
        if msg:
            msgs[chat] = msg
    return msgs

高级功能实现

好友管理功能

GetNewFriends()方法实现了新好友请求的获取与处理:

def GetNewFriends(self):
    """获取新的好友申请列表
    
    Returns:
        list: 新的好友申请列表,元素为NewFriendsElement对象,可直接调用Accept方法
    """
    self._show()
    self.SwitchToContact()
    self.SessionBox.ButtonControl(Name='ContactListItem').Click(simulateMove=False)
    NewFriendsList = [NewFriendsElement(i, self) for i in self.ChatBox.ListControl(Name='新的朋友').GetChildren()]
    AcceptableNewFriendsList = [i for i in NewFriendsList if i.acceptable]
    wxlog.debug(f'获取到 {len(AcceptableNewFriendsList)} 条新的好友申请')
    return AcceptableNewFriendsList

每个好友请求封装为NewFriendsElement对象,支持直接接受并设置备注和标签:

for friend in newfriends:
    remark = f'备注{friend.name}'
    friend.Accept(remark=remark, tags=tags)  # 接受好友请求,并设置备注和标签

群成员管理

GetGroupMembers()方法实现了群成员列表的获取:

def GetGroupMembers(self):
    """获取当前聊天群成员

    Returns:
        list: 当前聊天群成员列表
    """
    ele = self.ChatBox.PaneControl(searchDepth=7, foundIndex=6).ButtonControl(Name='聊天信息')
    try:
        uia.SetGlobalSearchTimeout(1)
        rect = ele.BoundingRectangle
        Click(rect)
    except:
        return 
    finally:
        uia.SetGlobalSearchTimeout(10)
    
    # ...成员列表提取逻辑...
    
    return members

技术挑战与解决方案

UI自动化的稳定性挑战

微信客户端的UI结构可能随版本变化,wxauto通过多种机制保证兼容性:

  1. 版本检查机制:在初始化时验证微信版本
  2. 灵活的控件定位:结合类名和搜索深度的控件查找
  3. 多语言支持:通过语言包适配不同语言版本的微信
def _checkversion(self):
    self.HWND = FindWindow(classname='WeChatMainWndForPC')
    wxpath = GetPathByHwnd(self.HWND)
    wxversion = GetVersionByPath(wxpath)
    if wxversion != self.VERSION:
        Warnings.lightred(self._lang('版本不一致', 'WARNING').format(wxversion, self.VERSION), stacklevel=2)
        return False

消息识别与提取

针对不同类型的消息,系统采用基于控件高度和内容特征的识别方法:

def _split(self, MsgItem):
    uia.SetGlobalSearchTimeout(0)
    MsgItemName = MsgItem.Name
    if MsgItem.BoundingRectangle.height() == WxParam.SYS_TEXT_HEIGHT:
        Msg = ['SYS', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()])]
    elif MsgItem.BoundingRectangle.height() == WxParam.TIME_TEXT_HEIGHT:
        Msg = ['Time', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()])]
    elif MsgItem.BoundingRectangle.height() == WxParam.RECALL_TEXT_HEIGHT:
        if '撤回' in MsgItemName:
            Msg = ['Recall', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()])]
        else:
            Msg = ['SYS', MsgItemName, ''.join([str(i) for i in MsgItem.GetRuntimeId()])]
    # ...其他消息类型处理...
    return ParseMessage(Msg, MsgItem, self)

应用示例:构建简单的微信机器人

基于wxauto.py的核心功能,可以快速构建一个自动回复机器人:

# 机器人实现示例
wx = WeChat()
print(f"当前登录用户: {wx.nickname}")

# 添加监听对象
wx.AddListenChat('文件传输助手')

# 消息处理循环
while True:
    messages = wx.GetListenMessage()
    if messages:
        for chat, msgs in messages.items():
            for msg in msgs:
                if msg.type == 'friend' or msg.type == 'self':
                    # 简单的echo回复
                    wx.SendMsg(f"收到消息: {msg.content}", chat.who)
    time.sleep(1)

总结与展望

wxauto.py通过精心设计的类结构和方法实现,为Windows微信客户端提供了强大而灵活的自动化能力。其核心优势在于:

  1. 完整的窗口控制:通过UIAutomation实现对微信界面的精准控制
  2. 多类型消息处理:支持文本、图片、文件和语音消息的处理
  3. 灵活的监听机制:可同时监控多个聊天对象
  4. 多语言支持:适配不同语言版本的微信客户端

未来可以进一步增强的方向:

  • 增加更多消息类型的支持(如表情包、小程序等)
  • 优化UI元素识别算法,提高版本兼容性
  • 增强异步消息处理能力,提升性能

通过深入理解wxauto.py的设计与实现,开发者可以构建更加复杂和强大的微信自动化工具,满足各种场景下的自动化需求。

要开始使用wxauto项目,请通过以下命令获取代码:

git clone https://gitcode.com/gh_mirrors/wx/wxauto

【免费下载链接】wxauto Windows版本微信客户端(非网页版)自动化,可实现简单的发送、接收微信消息,简单微信机器人 【免费下载链接】wxauto 项目地址: https://gitcode.com/gh_mirrors/wx/wxauto

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值