(原) Python之微信自动化

原创文章,请后转载,并注明出处。

Python的插件(组件)是相当多的,自动化方面也是。
虽然基于客户端微信去实现各种功能有点尴尬的感觉,但总还是比没有强。我总习惯一个问题寻找多种可能的解决方法,哪怕不是最优解。

能做个啥呢?比如把微信转换为语音播放,赞赏码付费信息处理等。
这里主要使用了两个库:pyautogui主要用于鼠标键盘的操作,uiautomation主要用于Win下程序的组件句柄控制。
uiautomation 模块中文说明
以下代码功能实现的是发现新收到的消息,程序部份思路还有问题。不适合复制粘贴。

import pyautogui as pauto
import uiautomation as uauto
import time

pic = ['wxd0.png','wxd1.png', 'wx10.png','wx11.png','wx12.png','wx21.png','wx30.png','wx31.png']
chat_content = []

def wx_mess():
    for p in pic:
            #print(p)
            a = pauto.locateOnScreen(p)
            if not a is None:
                x, y = pauto.center(a) # 获得文件图片在现在的屏幕上面的中心坐标
                pauto.moveTo(x,y,duration=0)  # 移动到图像位置
                pauto.move(-20,10)  # 图标偏移
                pauto.click()  # 点击

while True:
    time.sleep(3)
    wx=uauto.WindowControl(Name='微信',searchDepth=1)  # 绑定微信的主程序窗口
    wx.SetActive() # 激活程序

    search = wx.EditControl(Name='搜索')
    edit = wx.EditControl(Name='输入')
    messages = wx.ListControl(Name='消息')
    sendButton = wx.ButtonControl(Name='sendBtn')
    chat = wx.ListControl(Name='会话')
    
    # 是否有新消息
    new_content = messages.GetChildren()[-1].Name
    has = True
    for c in chat_content:
          # 已经包含了此句,不是新消息
          if c==new_content:
              has = False
              continue
    # 是新消息,添加到列表中
    if has:
       chat_content.append(new_content)
       print("新消息:", new_content)
      
    wx_mess()
    time.sleep(10)

再来一个,用于实现自动发送消息给微信好友。可改造自动广告机。

import uiautomation as auto
import time

wx=auto.WindowControl(Name='微信',searchDepth=1)  # 绑定微信的主程序窗口
# wx.SwitchToThisWindow()   # 切到到程序窗口
wx.SetActive() # 激活程序
# wx.CaptureToImage("a.png")  # 截图
search = wx.EditControl(Name='搜索')
edit = wx.EditControl(Name='输入')
messages = wx.ListControl(Name='消息')
sendButton = wx.ButtonControl(Name='sendBtn')
chat = wx.ListControl(Name='会话')
for item in chat.GetChildren():
      print(item.Name)
      
#search.Click()
#edit.SendKeys('梁华')
#time.sleep(1)
#edit.SendKeys("{Enter}")
#messages.SendKeys("测试信息")
#sendButton.Click()
#for item in messages.GetChildren():
#    print(item.Name)

我的文章一般是会持续更新的。
这里增加了语音播报功能,赞赏码付费OCR功能。
新消息的判断应该有点问题。
需要增加新消息对象获取。

#
#----------------------------------------------------------
# 功能:微信自动化
# 说明:自动获取赞赏码、聊天信息并播报
# 参数:
# 返回:
# 日期:2022年10月5日
# 开发:Ease.
# ----------------------------------------------------------
#

# 禁止所有INFO日志输出
import logging
logging.disable(logging.INFO)

from paddleocr import PaddleOCR, draw_ocr
import pyautogui as pauto
import uiautomation as uauto
import subprocess
import pyttsx3
import time
try:
    from PIL import Image
except ImportError:
    import Image

pic = ['wxd0.png','wxd1.png', 'wx10.png','wx11.png','wx12.png','wx21.png','wx30.png','wx31.png',"wxz01.png"]
chat_content = []
pay_file = 'pay.png'  # 赞赏付款截图

#
def wx_mess():
    for p in pic:
        a = pauto.locateOnScreen(p)
        if not a is None:
            x, y = pauto.center(a)                  # 获得文件图片在现在的屏幕上面的中心坐标
            pauto.moveTo(x-20,y+10,duration=0)      # 移动到图像位置
            pauto.click()                           # 点击
            
            # 是否为赞赏付款
            a = pauto.locateOnScreen("good01.png")
            if not a is None:
                pauto.screenshot(pay_file,region=(a.left-10,a.top+30,340,240))     # 截图
                result = ocr.ocr(pay_file, cls=True)
                engine.say("赞赏码到帐:" + result[2][1][0] + " " + result[3][1][0] + "," + result[0][1][0] + result[1][1][0] + "。" + result[4][1][0])  # 来自xx,收款金额xx,付款方留言xxx
                engine.runAndWait()                      

ocr = PaddleOCR(use_angle_cls=True, lang="ch")
old_mouse_position = pauto.position()                                           # 鼠标原位置
old_window = uauto.GetForegroundControl().GetTopLevelControl()                  # 原窗口句柄    
subprocess.Popen("C:\Tools\WeChat\WeChat.exe")
wx=uauto.WindowControl(Name='微信',searchDepth=1)                               # 绑定微信的主程序窗口

# 语音引擎
engine = pyttsx3.init()
engine.say("微信服务开始")
engine.runAndWait()

wx.SetActive()                                                                  # 激活微信程序

pauto.moveTo(wx.BoundingRectangle.left+100,wx.BoundingRectangle.top+100,duration=0) # 首先点击列表中的第一个人
pauto.click()                                                                  

# 获取各个控件句柄
search = wx.EditControl(Name='搜索')
edit = wx.EditControl(Name='输入')
messages = wx.ListControl(Name='消息')
sendButton = wx.ButtonControl(Name='sendBtn')
chat = wx.ListControl(Name='会话')

while True:
        if old_mouse_position==None:
            old_mouse_position = pauto.position()                                           # 鼠标原位置
            old_window = uauto.GetForegroundControl().GetTopLevelControl()                  # 原窗口句柄    
            wx.SetActive()                                                                  # 激活程序
            pauto.moveTo(wx.BoundingRectangle.left+100,wx.BoundingRectangle.top+100,duration=0) # 首先点击列表中的第一个人
            pauto.click()                                                                  

        wx_mess()
        
        # 是否有新消息
        if len(messages.GetChildren())>0:
            new_content = messages.GetChildren()[-1].Name
            has = True
            for c in chat_content:
                # 已经包含了此句,不是新消息
                if c==new_content:
                    has = False
                    continue
            # 是新消息,添加到列表中
            if has:
                chat_content.append(new_content)
                print("新消息:", new_content)
                engine.say(new_content)
                engine.runAndWait()  
                
        old_window.SetActive()                                                              # 恢复前台窗口
        pauto.moveTo(old_mouse_position,duration=0)                                         # 恢复鼠标位置
        time.sleep(10)
        old_mouse_position = None
    
engine.stop()

我在操作电脑的时候,是不想让它工作的。捕获键盘和鼠标,当发现有操作时则不进行后续操作。

#
#----------------------------------------------------------
# 功能:微信自动化
# 说明:自动获取赞赏码、聊天信息并播报
# 参数:
# 返回:
# 日期:2022年10月5日
# 开发:Ease.
# TODO:1. 鼠标移动时,不工作
# ----------------------------------------------------------
#

# 禁止所有INFO日志输出
import logging
logging.disable(logging.INFO)

from paddleocr import PaddleOCR, draw_ocr
import pyautogui as pauto
import uiautomation as uauto
import subprocess
import pyttsx3
import time
import keyboard
try:
    from PIL import Image
except ImportError:
    import Image

pic = ['wxd0.png','wxd1.png', 'wx10.png','wx11.png','wx12.png','wx21.png','wx30.png','wx31.png',"wxz01.png"]
chat_content = []
pay_file = 'pay.png'  # 赞赏付款截图

#
def wx_mess():
    for p in pic:
        a = pauto.locateOnScreen(p)
        if not a is None:
            x, y = pauto.center(a)                  # 获得文件图片在现在的屏幕上面的中心坐标
            pauto.moveTo(x-20,y+10,duration=0)      # 移动到图像位置
            pauto.click()                           # 点击
            
            # 是否为赞赏付款
            a = pauto.locateOnScreen("good01.png")
            if not a is None:
                pauto.screenshot(pay_file,region=(a.left-10,a.top+30,340,240))     # 截图
                result = ocr.ocr(pay_file, cls=True)
                engine.say("赞赏码到帐:" + result[2][1][0] + " " + result[3][1][0] + "," + result[0][1][0] + result[1][1][0] + "。" + result[4][1][0])  # 来自xx,收款金额xx,付款方留言xxx
                engine.runAndWait()                      

def onKey(e):
    global move_num
    move_num=move_num+1    

ocr = PaddleOCR(use_angle_cls=True, lang="ch")
old_mouse_position = pauto.position()                                           # 鼠标原位置
old_window = uauto.GetForegroundControl().GetTopLevelControl()                  # 原窗口句柄    
subprocess.Popen("C:\Tools\WeChat\WeChat.exe")
wx=uauto.WindowControl(Name='微信',searchDepth=1)                               # 绑定微信的主程序窗口

# 语音引擎
engine = pyttsx3.init()
engine.say("微信服务开始")
engine.runAndWait()

wx.SetActive()                                                                  # 激活微信程序

pauto.moveTo(wx.BoundingRectangle.left+100,wx.BoundingRectangle.top+100,duration=0) # 首先点击列表中的第一个人
pauto.click()                                                                  

# 获取各个控件句柄
search = wx.EditControl(Name='搜索')
edit = wx.EditControl(Name='输入')
messages = wx.ListControl(Name='消息')
sendButton = wx.ButtonControl(Name='sendBtn')
chat = wx.ListControl(Name='会话')

while True:
        if old_mouse_position==None:
            old_mouse_position = pauto.position()                                           # 鼠标原位置
            old_window = uauto.GetForegroundControl().GetTopLevelControl()                  # 原窗口句柄    
            wx.SetActive()                                                                  # 激活程序
            pauto.moveTo(wx.BoundingRectangle.left+100,wx.BoundingRectangle.top+100,duration=0) # 首先点击列表中的第一个人
            pauto.click()                                                                  

        wx_mess()
        
        # 是否有新消息
        if len(messages.GetChildren())>0:
            new_content = messages.GetChildren()[-1].Name
            has = True
            for c in chat_content:
                # 已经包含了此句,不是新消息
                if c==new_content:
                    has = False
                    continue
            # 是新消息,添加到列表中
            if has:
                chat_content.append(new_content)
                print("新消息:", new_content)
                engine.say(new_content)
                engine.runAndWait()  
                
        old_window.SetActive()                                                              # 恢复前台窗口
        pauto.moveTo(old_mouse_position,duration=0)                                         # 恢复鼠标位置
        # 等待
        start = time.perf_counter()
        move_num = 0  # 没有移动
        mouse = None
        keyboard.hook(onKey)
        while True:
            if pauto.position()!=mouse:
                move_num=move_num+1
            mouse = pauto.position()
            
            end = time.perf_counter()
            # 10秒后,判断是否有鼠标移动(正在工作)。有鼠标移动则继续循环。
            if end-start>10:
                if move_num<10:
                    break        
                else:
                    start = time.perf_counter()
                    move_num = 0
            
        old_mouse_position = None
    
engine.stop()

相关文章