PC自动化之pywinauto
官方文档: https://pywinauto.readthedocs.io/en/latest/contents.html
[安装]
pip install pywinauto
[使用]
from pywinauto import application # 创建应用程序对象并打开应用程序 app = application.Application() app.start('your_application.exe') # 连接到应用程序窗口 app.connect(title='Window Title') # 获取窗口对象 window = app.window(title='Window Title') # 获取子控件 child = window.child_window(class_name='UIAutomationClassName') # 获取子控件的UI元素信息 element_info = child.uia_element_info # 打印UI元素信息 print(element_info)
1.其中的点击事件,需要使用click_input代替click(无法正常使用)
2.其中涉及的鼠标和键盘的相关事件,推荐使用单独包
from pywinauto import mouse, keyboard
3.元素的操作对象是一个dialog, 所以应用需要指定
app.window(title='', class_name='')
可以指定名称或类名称
4.查找元素
win.child_window(title='', control_type='',found_index=0)
注: 如果存在多个元素, 则可以通过索引指定:found_index
指定名称和控件类型
常见控件类型:
Window: 窗口
ToolBar: 导航
Button: 按钮
ListItem: 聊天列表
Text:聊天内容
5.查询所有Windows下的窗口元素
# 查询当前内置浏览器窗格信息 wins = pywinauto.findwindows.find_elements(backend='uia') print('所有窗口:', wins)
# 查找指定窗口的进程,类名,窗口名称(任务栏中展示的名称)等情况
pid = 0
for win in wins:
print('=======================')
print(dir(win))
print(win.name) # 窗口名称
# print(win.control_id) # 都是0
# print(win.process_id)
# print(win.automation_id)
print(win.class_name) # 类名
# print(win.control_id) # 都是0
print(win.runtime_id) # (id, 进程ID)
if win.class_name == 'Chrome_WidgetWin_0':
pid = win.runtime_id[1]
# 使用handle的方式链接窗口并执行操作
app2 = Application(backend='uia').connect(handle=pid)
# print(app2.window().print_control_identifiers())
app2.window().child_window(title='关闭', control_type='Button', found_index=0).click_input()
使用实例:
1)自动打开微信链接
import random import time from pywinauto import mouse, keyboard import pywinauto.findwindows from pywinauto.application import Application import pyautogui # 连接方式1) # app = Application(backend='uia').connect(process=19004) # 连接方式2) app = Application(backend='uia').connect(path=r'D:\software\WeChat\WeChat.exe') # 该窗口中的对话框, 方便查看当前的窗口或窗格情况 # print(app.windows()) # Chrome_WidgetWin_0 # 打开 # app = Application(backend='uia').start('D:\software\WeChat\WeChat.exe') # time.sleep(5) # 拿到微信主窗口 win_main_dialog = app.window(title='微信', class_name='WeChatMainWndForPC') # 判断是否未dialog, 一个微信就是一个dialog -->窗口 # print(win_main_dialog.is_dialog) # print(win_main_dialog.wrapper_object()) # 给空间画一个红色框便于看出 win_main_dialog.draw_outline(colour='red') # 打印当前所有空间和属性 # win_main_dialog.print_control_identifiers(depth=None, filename=None) time.sleep(1) def get_element_position(ele): """获取元素的中心点位置""" element_position = ele.rectangle() # 算出中心点位置 center_position = (int((element_position.left + element_position.right) / 2), int((element_position.top + element_position.bottom) / 2)) return center_position def send_msg(): # 找到文件传输助手 file_helper_ele = win_main_dialog.child_window(title="文件传输助手已置顶", control_type="ListItem") mouse.click(button='left', coords=get_element_position(file_helper_ele)) # 获取输入框元素, 并模拟输入 edit_ele = win_main_dialog.child_window(title="文件传输助手", control_type="Edit") time.sleep(2) edit_ele.type_keys("hello") keyboard.send_keys("{ENTER}") def click_buttons(): '''分别进行点击''' win_main_dialog.child_window(title="聊天", control_type="Button").click_input() time.sleep(2) win_main_dialog.child_window(title="通讯录", control_type="Button").click_input() time.sleep(2) win_main_dialog.child_window(title="朋友圈", control_type="Button").click_input() time.sleep(2) def gui(): # 使用pyautogui方式是比较固定(坐标)的方式 pyautogui.click(x=622, y=183, clicks=1, interval=0.1) time.sleep(random.randint(3, 5)) pyautogui.click(x=756, y=78, clicks=1, interval=0.1) ''' depth: 打印深度, 缺省最大深度 filenmae: 返回的标识存成文件, 可以指定 eg:a.txt ''' # 查找主窗口下的某个窗口 # chat_list = win_main_dialog.child_window(control_type='List', title='会话') # first = chat_list.items()[0] # 第一个聊天项, 支持循环, 索引 # chat_list.scroll(direction='down', amount='page') # 向下滚动一页 # first.focus() def main(): # 找到聊天框 chat_list_ele = win_main_dialog.child_window(title="聊天", control_type="Button") mouse.click(button='left', coords=get_element_position(chat_list_ele)) time.sleep(1) # 找到指定聊天人 ln = win_main_dialog.child_window(title="Learning已置顶", control_type="ListItem") mouse.click(button='left', coords=get_element_position(ln)) time.sleep(1) # 找到指定链接并点击 lk = win_main_dialog.child_window(title=r"https://www.cnblogs.com/xingxia", control_type="ListItem") mouse.click(button='left', coords=get_element_position(lk)) time.sleep(random.randint(3, 5)) # 关闭内置浏览器 # 1) 查询当前内置浏览器窗格信息 wins = pywinauto.findwindows.find_elements(backend='uia') print('所有窗口:', wins) pid = 0 for win in wins: print('=======================') print(dir(win)) print(win.name) # 窗口名称 # print(win.control_id) # 都是0 # print(win.process_id) # print(win.automation_id) print(win.class_name) # 类名 # print(win.control_id) # 都是0 print(win.runtime_id) # (id, 进程ID) if win.class_name == 'Chrome_WidgetWin_0': pid = win.runtime_id[1] app2 = Application(backend='uia').connect(handle=pid) # print(app2.window().print_control_identifiers()) app2.window().child_window(title='关闭', control_type='Button', found_index=0).click_input() if __name__ == '__main__': main() # 自动化主流程 # send_msg() # 发送消息 # click_buttons() # gui()
说明:
1.其中元素定位软件需要借助: inspect.exe 或者 UISpy
这里推荐使用UISpy,但是不能通过点选方式获取元素信息,需要一级一级查找,有些不太友好
inspect.exe虽然可以通过点选方式查找元素,但是具体的元素信息展示的不正确
PC端的自动化, 除了可以使用pywinauto之外,还有其他的工具可以选择, 例如:uiautomation
对比PyWinAuto和uiautomation
PyWinAuto和uiautomation都是自动化测试工具,它们都可以模拟用户的操作来测试应用程序的功能。但是PyWinAuto是一个Python库,可以跨平台使用,而uiautomation是一个Windows平台的测试工具。除此之外,PyWinAuto提供更多的GUI操作函数和更好的文档支持,而uiautomation则更加适合对Windows应用程序进行测试。
安装
pip install uiautomation
github: https://github.com/yinkaisheng/Python-UIAutomation-for-Windows
常见问题:
1.
pywinauto.findwindows.ElementNotFoundError
进程没加载完成,就执行查找工作,通过time.sleep()就可以解决
app = pywinauto.Application(backend='uia').start(r"D:\Program Files\PremiumSoft\Navicat for MySQL\navicat.exe") # 方式一 # 使用雷鸣选择窗口,打印窗口所有控件 time.sleep(5) dlg = app['TNavicatMainForm'] dlg.print_control_identifiers()