聊聊 PC 端自動化最佳方案 – Pywinauto

1. 前言

大家好,我是安果!

上一篇文章,聊到 PC 端的一種自動化方案:WinAppDriver

聊聊 PC 端自動化最佳方案 – WinAppDriver

有小夥伴後台給我留言,說「 pywinauto 」作為 WinAppDriver 的替代方案,也能完美完成 PC 端的自動化

2. 介紹

Pywinauto,完全由 Python 構建的一個模塊,可以用於自動化 Windows 上的 GUI 應用程序

同時,它支持鼠標、鍵盤操作,在元素控件樹較複雜的界面,可以輔助我們完成自動化操作

項目地址://github.com/pywinauto/pywinauto

支持的應用為下面 2 大類:

  • Win32 API

    包含 MFC、VB6、VCL、simple WinForms controls and most of the old legacy apps

  • MS UI Automation

    包含 WinForms、WPF、Store apps、Qt5, browsers

其中

win32 API 的 backend 為「 win32 」

MS UI Automation 的 backend 為「 uia 」

3. 元素控件

和 WinAppDriver 類似,在編寫自動化腳本之前,我們需要先獲取元素控件的各類屬性值

獲取元素控件有 2 種方式:

  • 窗口內置方法

  • 檢查工具

其中

窗口對象內置的 2 個方法都可以打印出當前頁面的元素控件樹

# 窗口對象中內置方法,打印窗體內所有元素控件
# 方式一:
窗體對象.print_control_identifiers()

# 方式二
窗體對象.dump_tree()

常用的檢查工具也包含 2 種,分別是:Inspect.exe、Spy++

4. 實戰一下

在實戰之前,我們先安裝依賴包 pywinauto

# 安裝依賴
pip3 install pywinauto

接下來,我們還是以上篇文章中的例子來講解完整的實現過程

4-1  打開微信客戶端

首先,通過檢查工具判斷應用的 backend 屬性值,PC 端微信的 backend 為「 uia 」

然後,實例化一個「 Application 」類

最後,使用該對象內置的函數創建一個應用對象

import pywinauto
from pywinauto.application import Application

# 獲取應用對象
# 三種方式任選一種
# 方式一:應用進程pid(連接)
app = Application(backend='uia').connect(process=pid)

# 方式二:應用完整路徑(連接)
app = Application(backend='uia').connect(path="D:\Program Files (x86)\Tencent\WeChat\WeChat.exe")

# 方式三:打開應用(打開)
app = Application(backend='uia').start('D:\Program Files (x86)\Tencent\WeChat\WeChat.exe')

需要指出的是,獲取應用對象有上面 3 種方式,可以按需使用

4-2  獲取窗體對象

通過檢查工具獲取窗體的屬性列表,然後使用應用對象 + 窗體屬性獲取微信首頁的窗體對象

image

實現代碼如下:

from pywinauto.win32functions import SetFocus

# 獲取窗口對象
# 通過title及ClassName獲取窗體對象
self.weixin_pc_window = self.app.window(title=u"微信", class_name="WeChatMainWndForPC")

self.weixin_pc_window.set_focus()

4-3  切換到聊天列表

獲取左側聊天切換按鈕,獲取其坐標位置,模擬點擊進入到聊天列表頁面

from pywinauto import mouse

def __get_element_postion(self, element):
    """獲取元素的中心點位置"""
    # 元素坐標
    element_position = element.rectangle()
    # 算出中心點位置
    center_position = (int((element_position.left + element_position.right) / 2),
                           int((element_position.top + element_position.bottom) / 2))
    return center_position

def start(self):
    # 1、獲取左側【聊天】切換元素
    chat_list_element = self.weixin_pc_window.child_window(title="聊天", control_type="Button")
    # 2、點擊進入到聊天列表
    mouse.click(button='left',
                    coords=self.__get_element_postion(chat_list_element))

4-4  進入聊天頁面,輸入內容並發送

獲取「 文件聊天助手 」元素,點擊進入到聊天頁面,找到輸入框元素,使用內置方法輸入內容,最後使用鍵盤模擬點擊「 Enter 」鍵,發送消息

from pywinauto import mouse

# 3、點擊【文件傳輸助手】進入到聊天頁面
file_helper_element = self.weixin_pc_window.child_window(title="文件傳輸助手", control_type="ListItem")

mouse.click(button='left',
                    coords=self.__get_element_postion(file_helper_element))
# 4、獲取輸入框元素,模擬輸入
        edit_element = self.weixin_pc_window.child_window(title=r"輸入", control_type="Edit")

sleep(2)
# 輸入內容
edit_element.type_keys("星安果")
# 使用鍵盤模擬回車,即:發送
send_keys('{ENTER}')

4-5  釋放資源

完成操作後,可以調用應用對象的「 kill() 」函數關閉進程,釋放掉資源

def teardown(self):
    """釋放資源"""
    # 結束進程,釋放資源
    self.app.kill()

5. 最後

上例中使用 pywinauto 完成了一個簡單的發送消息的自動化步驟

實際項目中,結合鼠標、鍵盤可以實現很多複雜場景的自動化,對這部分有興趣的可以點擊文末的「 閱讀原文 」去了解

pywinauto 和 WinAppDriver 都能很好的完成 PC 端的自動化,但是由於 WinAppDriver 支持 Appium,在腳本語法簡潔性方面可能更有優勢

文中的所有源碼我已經上傳到公眾號後台,關注公眾號「 AirPython 」後,回復關鍵字「 winauto 」獲取完整源碼

如果你覺得文章還不錯,請大家 點贊、分享、留言 下,因為這將是我持續輸出更多優質文章的最強動力!