首页 > 系统相关 >用python的pywinauto组件控制微信Windows版

用python的pywinauto组件控制微信Windows版

时间:2023-04-05 22:33:30浏览次数:47  
标签:username .__ return item python pywinauto self Windows msg

使用pywinauto组件可以比较容易的操纵微信Windows版进行信息发送和接受

 

前提如下

1、已经安装有关python组件。

2、微信已经打开和登录,下面的代码不负责登录操作。

3、微信版本3.9.2.23

具体实现有两个类

1、帮助类Helper

import datetime


class Helper:
    """
    帮助类
    """

    @staticmethod
    def print(msg):
        """
        打印和记录消息
        :param msg:
        :return:
        """
        time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f'{msg} 当前时间:{time}')

    @staticmethod
    def get_time():
        """
        获取时间字符串%Y-%m-%d %H:%M:%S
        :return:
        """
        return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")


class AutoMsg:
    """
    定义自动化操作的结果类
    """

    def __init__(self):
        self.result = 0
        self.message = ""
        self.errcode = ""

    def get_result(self):
        """
        获取结果信息 1 成功 -1失败 0未知
        :return:
        """
        return self.result

    def get_errcode(self):
        """
        获取错误的编码
        :return:
        """
        return self.errcode


class UserNotFoundError(Exception):
    """
    微信用户没有找到异常
    """
    pass


class AppNotFoundError(Exception):
    """
    没有找到应用程序
    """
    pass


class EleNotFoundError(Exception):
    """
    没有找到应用程序
    """
    pass

 

2、微信操控类Wechat

import time
import pyautogui
from pywinauto.findwindows import ElementNotFoundError

from helper import *
from pywinauto.application import Application, ProcessNotFoundError


class Wechat:
    """
    微信的自动化处理
    """

    def __init__(self, path):
        """
        创建微信自动化的实例
        :param path:
        :return:
        """
        self.__path = path
        # 微信的主窗口对象
        self.__main_win = None
        # 微信输入框的对象
        self.__input_msg_box = None
        # 查询输入框对象
        self.__search_box = None
        # 微信默认显示的会话列表框
        self.__dia_list = None
        # 输入框的标题的button
        self.__input_title_btn = None
        # 右侧面板
        self.__right_panel = None

    @staticmethod
    def __get_main_win(path):
        """
        获取微信的主窗口
        :param path:传入微信的安装路径
        :return:
        """
        # 获取进程ID
        try:
            app = Application(backend='uia').connect(path=path)
        except ProcessNotFoundError:
            raise AppNotFoundError("微信程序还没有打开")
        main_win = app.window(class_name='WeChatMainWndForPC')
        # if not app.top_window():
        Helper.print(f'     获取主程序 pid为{app.process}')
        return main_win

    def __is_latest_user(self, username):
        """
        是否为最近聊天的用户
        :param username:微信聊天的用户
        :return:
        """
        result = False
        if self.__dia_list and self.__input_title_btn:
            # 检查会话框是不是选中当前用户
            item_list = self.__dia_list.get_items()
            for item in item_list:
                if item.is_selected() and item.element_info.name == username:
                    # 会话选中当前用户
                    result = True
                    break
            if result:
                # 如果输入框对象存在并且等于当前用户
                result = self.__input_title_btn.window_text().strip() == username
        if result:
            Helper.print("     ~~~~对话用户没变~~~~")
        return result

    def __auto_by_search(self, parent_ele, username):
        """
        先选择搜索框,再进行发送信息
        :param parent_ele:父窗口的对象
        :param username:发送的用户
        :return:
        """
        # 搜索框的名称
        Helper.print('      ===通过搜索查找用户===')
        # select_item = self.__search_box = select_item
        # selectItem.draw_outline(colour='red')
        self.__search_box.click_input()
        pyautogui.hotkey('ctrl', 'a')
        pyautogui.hotkey('delete')
        Helper.print('      输入筛选词语')
        self.__search_box.type_keys(username, with_spaces=False)
        Helper.print("      等待2秒出筛选结果")
        # 等待筛选结果出来
        time.sleep(2)
        # 选择下来项目
        Helper.print('      选择第一个搜索出来的用户')
        # 通过列表来查询
        select_item = None
        target_ele = parent_ele.children()[1].children()[0]
        items = target_ele.get_items()
        for item in items:
            if item.element_info.name == username:
                select_item = item
                break
        Helper.print("      ------从搜索列表中找到用户------")
        if select_item:
            Helper.print('      用户列表查找完毕,点击控件')
            select_item.click_input()
        else:
            raise UserNotFoundError(f"没有找到名称为\"{username}\"的用户")

    def __auto_by_list(self, username):
        """
        直接寻找用户的控件
        :param username:发送的用户
        :return:
        """
        if not self.__dia_list:
            self.__dia_list = self.__main_win.child_window(title="会话", control_type="List").wrapper_object()
        dia_list = self.__dia_list
        Helper.print(f"      查找\"{username}\"的控件")
        select_item = None
        for item in dia_list.get_items():
            if item.element_info.name == username:
                select_item = item
                break
        if select_item and select_item.is_visible():
            # 如果已经找到下拉控件
            select_item.click_input()
        else:
            # 根据会话框找到上级窗口(参照Inspect)
            parent_ele = dia_list.parent().parent().parent().parent()
            self.__auto_by_search(parent_ele, username)

    def __init_elements(self, username):
        """
        获取用户控件,初始化各个参数
        :param username:
        :return:
        """
        if not self.__path:
            raise Exception("微信exe路径不能为空!")
        if not self.__main_win:
            self.__main_win = Wechat.__get_main_win(self.__path)
        try:
            self.__main_win.set_focus()
        except ElementNotFoundError:
            raise EleNotFoundError("核心窗口对象没有找到,请检测微信是否已经登录")
        if not self.__search_box:
            self.__search_box = self.__main_win.child_window(title='搜索', control_type="Edit").wrapper_object()
        # 获取Edit控件的值,判断是否为空
        if len(self.__search_box.get_value().strip()) > 0:
            # 如果正在搜索中,删除按钮会出现
            del_btn = self.__search_box.parent().children()[-1]
            del_btn.click_input()
        # ----1、尝试选择下拉控件----
        if not self.__is_latest_user(username):
            self.__auto_by_list(username)
            # 等待右边的输入框的显示
            time.sleep(1)
        if not self.__input_msg_box:
            self.__input_msg_box = self.__main_win.child_window(title="输入", control_type="Edit").wrapper_object()
        if not self.__right_panel:
            # 根据元素位置来进行编程(参照inspect)
            self.__right_panel = self.__input_msg_box.parent().parent().parent().parent().parent().parent()
        # ----2、如果已经获取到输入框,则检查一下信息框是否存在----
        if not self.__input_title_btn:
            # Helper.print("      input_title_btn为空,查找一下控件")
            # 如果还没有找到这个输入框的标题控件
            item_list = self.__right_panel.children()
            if len(item_list) > 0:
                # 从右侧面板的第一个控件(右侧顶部面板)开始查找(参照inspect)
                item_list = item_list[0].descendants(title=username, control_type="Button")
                if len(item_list) == 0:
                    raise Exception("没有找到当前用户的对话框!")
                self.__input_title_btn = item_list[0]
        # Helper.print("      input_title_btn element_info.name is " + self.__input_title_btn.element_info.name)
        if self.__input_title_btn.element_info.name != username:
            # 如果输入框的标题不是当前用户
            raise Exception("没有找到当前用户的对话框!")
        # Helper.print(f"      \"{username}\"对话框已经找到,查找用户正确!")

    def __send_message(self, username, send_msg):
        """
        向特定的用户发送消息
        :param username: 对方微信的用户名称
        :param send_msg: 发送的消息
        :return:
        """
        # 打开微信的快捷键
        Helper.print("--开始发送信息--")
        self.__init_elements(username)
        # ----3、到了用户对话框,才开始输入对话信息----
        self.__input_msg_box.click_input()
        self.__input_msg_box.type_keys(send_msg, with_spaces=True)
        # 回车发送
        pyautogui.hotkey('enter')
        Helper.print("--结束发送信息--")

    def __get_message(self, username, other_side=False):
        """
        获取最后的会话信息
        :param username: 微信用户名称
        :param other_side: 只读取对方的信息,只适合双人会话
        :return:
        """
        message = None
        Helper.print("--开始查找信息--")
        self.__init_elements(username)
        dia_list = self.__right_panel.descendants(title="消息", control_type="List")
        if len(dia_list) > 0:
            # 获取List中最后一个控件
            last_item = dia_list[0].get_item(-1)
            message = last_item.element_info.name
            if other_side:
                # 检测是否为对方的输入
                btn_list = last_item.descendants(title=username, control_type="Button")
                if len(btn_list) == 0:
                    # 如果不是对方的输入信息
                    message = None
        Helper.print("--结束查找信息--")
        return message

    @staticmethod
    def __wrap_errcode(exception):
        """
        判断异常的类型,并设置错误代码
        :param exception:
        :return:
        """
        result = ""
        if isinstance(exception, UserNotFoundError):
            result = "3-01用户不存在"
        elif isinstance(exception, EleNotFoundError):
            result = "2-01控件不存在"
        elif isinstance(exception, AppNotFoundError):
            result = "1-01程序没启动"
        return result

    def get_last_msg(self, username, other_side=False):
        """
        获取最后的会话
        :param username: 微信用户名称
        :param other_side: 只读取对方的信息,只适合双人会话,适合自动回复场景
        :return:
        """
        auto_msg = AutoMsg()
        try:
            message = self.__get_message(username, other_side)
            auto_msg.result = 1
            auto_msg.message = message
        except Exception as e:
            auto_msg.result = -1
            auto_msg.message = str(e)
            auto_msg.errcode = Wechat.__wrap_errcode(e)
        if other_side and auto_msg.message is None:
            # 如果要读取对方的信息,并且读不到。
            auto_msg.result = -1
        return auto_msg

    def send_msg(self, username, send_msg):
        """
        向特定的用户发送消息
        :param username: 对方微信的用户名称
        :param send_msg: 发送的消息
        :return:
        """
        auto_msg = AutoMsg()
        try:
            self.__send_message(username, send_msg)
        except Exception as e:
            auto_msg.result = -1
            auto_msg.message = str(e)
            auto_msg.errcode = Wechat.__wrap_errcode(e)
        if auto_msg.result == 0:
            auto_msg.result = 1
        return auto_msg

 

测试代码如下:

调试代码时,对照着inspect.exe比较方便。

from wechat import *
import random

if __name__ == '__main__':
    path = "D:\\WeChat\\WeChat.exe"
    # 消息内容
    num = random.randint(10000, 40000)
    send_msg = f"2023“网聚职工正能量 争做中国好网民”活动启动.{num}"
    # pyautogui.hotkey('ctrl', 'alt', 'w')
    chat = Wechat(path)
    user_name = '文件传输助手'
    info = chat.send_msg(user_name, send_msg)
    if info.result == -1:
        print(f"错误代码是:{info.errcode},错误信息是:{info.message}")

 

欢迎沟通交流  

 

标签:username,.__,return,item,python,pywinauto,self,Windows,msg
From: https://www.cnblogs.com/fubeibei/p/17291160.html

相关文章

  • Python基础(四)爬虫
    python爬虫系列文章网上搜素的系列文章记录一下后续可能会用https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzI3NzI1MzY4Mw==&action=getalbum&album_id=1786298272630816773#wechat_redirect1.requests请求2.User-Agent伪装from selenium import webdriverheader......
  • python 复制幻灯片并替换相应文字作为新的幻灯片_循环替换
    #encoding=utf8#-*-coding:utf-8-*-#pipinstallpython-pptx-ihttps://pypi.tuna.tsinghua.edu.cn/simple#pipinstallpython-docx-ihttps://pypi.tuna.tsinghua.edu.cn/simple#pipinstallpandas-ihttps://pypi.tuna.tsinghua.edu.cn/simplefrompptximp......
  • python 合并多个PPT
    #encoding=utf8#-*-coding:utf-8-*-#pipinstallaspose.slides-ihttps://pypi.tuna.tsinghua.edu.cn/simpleimportaspose.slidesasslidesfrompptximportPresentation#导入PPT库importwin32com.client,sysfromglobimportglob#打開第一張PPTwith......
  • CS50-Python实验3,4
    Week3ExceptionsFuelGauge题目描述:输入分数字符串,判断并输出相应的百分数;特例不足1%输出E,超出99%输出F思路:1,从字符串中取出x,y;2,按题中要求计算输出;题解:whileTrue:try:##取出x,yx,z,y=input("Fraction:")x,y=int(x),int(y)......
  • Golang入门教程(一)GOPATH与工作空间(Windows)
    https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/01.2.md Windows环境:下面我就以mymath为例来讲述如何编写应用包:cd$GOPATH/srcmkdirmymath//我的环境:$GOPATH=c:\mygo新建文件sqrt.go,内容如下://$GOPATH/src/mymath/sqrt.go源码如......
  • 流媒体技术学习笔记之(十一)Windows环境运行EasyDarwin
     流媒体平台框架下载安装Github下载下载地址:https://github.com/EasyDarwin/EasyDarwin/releases解压安装选择Windows安装平台的安装包(下载解压) 把解压生成的文件夹重命名放在本地磁盘,我这里测试放在E盘: 介绍其中的来个批处理文件:start.batWindows调试运......
  • python打印各种图形
    fewf#打印各种图形#正方形n行n列#***#***#***defsquare1(n:int)->None:foriinrange(n):forjinrange(n):print('*',end='')print()#长方形n行n+2列#*****#*****#*****def......
  • nohup python app.py 1>log.log 2>&1 & 这句话代码咋解释呀,不太明白
    nohuppythonapp.py1>log.log2>&1&这句话代码咋解释呀,不太明白 GPT给的答案 克隆ChatGpt功能nohuppythonapp.py1>log.log2>&1&这句话代码咋解释呀,不太明白  这个命令可以分成几部分:-`nohup`:意思是不挂断,即使终端关闭或者用户退出登录,进程也将继续运行。-......
  • python---飞机大战小游戏(提供源码)
    项目准备:本项目在pycharm平台实现,需要安装pygame等模块游戏功能:敌机会从不同位置出现且具有不同的速度,飞机可以发射子弹击毁敌机,飞机触碰到敌机会被击落,游戏结束效果演示飞机大战视频演示完整代码项目主要有两个文件构成,分别是plane_main.py文件和plane_sprites.py文件。plane_mai......
  • Python __ Pandas __ Dataframe 实验课
    基于Dataframe实现以下功能:导入directory.csvimportnumpyasnpimportpandasaspdfdata=pd.read_csv('F:\\directory.csv')dfx=pd.DataFrame(fdata)starbucks=pd.DataFrame(fdata)显示数据集的基本信息print(fdata.head())print(fdata.info())print(fdata.describe(......