python-桌面软件自动化(二) (pywinauto模拟鼠标键盘)

        我们先回顾下通过pywinauto操作控件需要以下几个步骤:
        第一步 :创建实例化对象,得到的app是Application对象
        第二步 :选择窗口 ,得到的窗口是WindowSpecification对象
        第三步:基于WindowSpecification对象使用其方法再往下查找,定位到具体的控件
        第四步:使用控件的方法属性执行我们需要的操作
接下来我们先看一个实例代码,(确保电脑版微信已经登录且前台显示在桌面上)按照上面的步获
取微信的搜索文本框并点击,代码如下:

from pywinauto import Application
# 第一步连接已有微信进程创建实例化对象(进程id在 任务管理器-详细信息 可以查看)
微信主程序 = Application(backend='uia').connect(process=18364)
# 第二步拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
# 第三步通过child_window方法查找搜索文本框
搜索 = 微信窗口.child_window(control_type='Edit', title='搜索')
# 第四步进行操作点击控件
搜索.click_input()

打印元素

        inspect可以查看窗口控件的的所有层级结构,同样我们也可以通过代码将控件下的所有子控件及其属性以树形结构打印出来。
        dlg. print_control_identifiers(depth=None, filename=None)
        depth:打印的深度,缺省时打印最大深度。
        filename:将返回的标识存成文件(生成的文件与当前运行的脚本在同一个路径下)
        比如: print_control_identifiers(filename =’层级关系.txt’) 

from pywinauto import Application
# 连接已有微信进程(进程号在 任务管理器-详细信息 可以查看,项目中一般根据进程名称自动获取)
微信主程序 = Application(backend='uia').connect(process=13116)
# 拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
微信窗口.restore()
# 打印当前窗口的所有controller(控件和属性)
# 源码内部函数名链式赋值了,print_ctrl_ids = dump_tree = print_control_identifiers, 都能

微信窗口. print_control_identifiers(depth=None, filename='微信结构.txt')

打印出来的文档树就是inspect中的控件树完全展开的样子,都是有层级的,和微信程序中的各个元素一 一对应的:

控件常用的方法属性

上节课我们学习了最常用的两个方法:

ctrl.click_input() # 最常用的点击方法,一切点击操作的基本方法(底层调用只是参数不同),左键单击,使用时一般都使用默认不需要带参数
# 键盘输入,底层还是调用keyboard.send_keys
ctrl.type_keys(keys, pause = None, with_spaces = False,)
        # keys:要输入的文字内容
        # pause:每输入一个字符后等待时间,默认0.01就行
        # with_spaces:是否保留keys中的所有空格,默认去除0

下面总结了大部分常用方法,基本可以满足所有场景的操作,如下

# 鼠标键盘操作
# 下面只列举常用形式,他们有很多默认参数但不常用,可以在源码中查看
ctrl.right_click_input() # 鼠标右键单击
ctrl.double_click_input(button ="left", coords = (None, None)) # 左键双击

ctrl.press_mouse_input(coords = (None, None)) # 指定坐标按下左键,不传坐标默认左上角
ctrl.release_mouse_input(coords = (None, None)) # 指定坐标释放左键,不传坐标默认左上角
ctrl.move_mouse_input(coords=(0, 0)) # 将鼠标移动到指定坐标,不传坐标默认左上角
ctrl.drag_mouse_input(dst=(0, 0)) # 将ctrl拖动到dst,是press-move-release操作集合
# 控件的常用属性
ctrl.children_texts() # 所有子控件的文字列表,对应inspect中Name字段
ctrl.window_text() # 控件的标题文字,对应inspect中Name字段
# ctrl.element_info.name
ctrl.class_name() # 控件的类名,对应inspect中ClassName字段,有些控件没有类名
# ctrl.element_info.class_name
ctrl.element_info.control_type # 控件类型,inspect界面LocalizedControlType字段的英文名
ctrl.is_child(parent) # ctrl是否是parent的子控件
ctrl.legacy_properties().get('Value') # 可以获取inspect界面LegacyIAccessible开头的一系
列字段,在源码uiawraper.py中找到了这个方法,非常有用,如某些按钮显示值是我们想要的,但是
window_text获取到的是固定文字‘修改群昵称’,这个值才是我们修改后的新名字
# 控件常用操作
ctrl.draw_outline(colour='green') # 控件外围画框,便于查看,支持'red', 'green', 'blue'
ctrl.print_control_identifiers(depth=None, filename=None) # 打印其包含的元素,详见打印
元素
ctrl.scroll(direction, amount, count=1,) # 滚动
# direction :"up", "down", "left", "right"
# amount:"line" or "page"
# count:int 滚动次数
ctrl.capture_as_image() # 返回控件的 PIL image对象 可使用save()方法保存
ret = ctrl.rectangle() # 控件上下左右坐标,(L123, 525, R600, B561)

接下来我们对其中一些方法进行举例:

接下来我们对其中一些方法进行举例:

1. 清空文本框

我们前面学习了利用type_keys() 方法输入文本,但是如果当前输入框中有文本时,输入的字符串会拼接在已有的文本后面,所以我们需要先清空文本框再输入。清空原理很简单就是先通过ctrl+a选中所有,然后再type_keys()替换,和我们选中然后修改一样的。代码如下:

from pywinauto import Application
import win32gui
# 根据应用程序窗口名获得句柄
句柄 = win32gui.FindWindow(None, '微信')
# 通过句柄连接已有微信进程
微信主程序 = Application(backend='uia').connect(handle=句柄)
# 拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
微信窗口.restore()
搜索 = 微信窗口.child_window(control_type='Edit', title='搜索')
搜索.click_input()
搜索.type_keys("有霸夫很帅")

# 先ctrl+a选中所有然后再type_keys替换,和我们选中然后修改一样的
搜索.type_keys('^a').type_keys('那确实')

输入对照表:

SHIFT         +
CTRL         ^
ALT         %
空格键         {SPACE}
BACKSPACE         {BACKSPACE}、{BS} or {BKSP}
BREAK         {BREAK}
CAPS LOCK         {CAPSLOCK}
DEL or DELETE         {DELETE} or {DEL}
DOWN ARROW         {DOWN}
END         {END}
ENTER         {ENTER} or ~
ESC         {ESC}
HELP         {HELP}
HOME         {HOME}
INS or INSERT         {INSERT} or {INS}
LEFT ARROW         {LEFT}
NUM LOCK         {NUMLOCK}
PAGE DOWN         {PGDN}
PAGE UP        {PGUP}
PRINT SCREEN         {PRTSC}
RIGHT ARROW         {RIGHT}
SCROLL LOCK         {SCROLLLOCK}
TAB         {TAB}
UP ARROW         {UP}
+         {ADD}
-         {SUBTRACT}
*         {MULTIPLY}
/         {DIVIDE}

1. 清空文本框
我们前面学习了利用type_keys() 方法输入文本,但是如果当前输入框中有文本时,输入的字符串会拼接在已有的文本后面,所以我们需要先清空文本框再输入。清空原理很简单就是先通过ctrl+a选中所有,然后再type_keys()替换,和我们选中然后修改一样的。代码如下:

from pywinauto import Application
import win32gui
# 根据应用程序窗口名获得句柄
句柄 = win32gui.FindWindow(None, '微信')
# 通过句柄连接已有微信进程
微信主程序 = Application(backend='uia').connect(handle=句柄)
# 拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
微信窗口.restore()

# 保存微信窗口到 微信窗口.png
截图 = 微信窗口.capture_as_image() # 返回控件的 PIL image对象
截图.save('微信窗口.png') # 保存图像

        capture_as_image() 方法 返回的其实是控件的 PlLimage对象,所以可用该方法的属性方法,比如save()可以图像保存到磁盘。

3.滚动条使用

from pywinauto import Application
import win32gui
# 根据应用程序窗口名获得句柄
句柄 = win32gui.FindWindow(None, '微信')
# 通过句柄连接已有微信进程
微信主程序 = Application(backend='uia').connect(handle=句柄)
# 拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
微信窗口.restore()
# 滑动一页会话列表
会话列表 = 微信窗口.child_window(control_type='List', title='会话')
会话列表.scroll('down', 'page', count=1)

4.控件鼠标操作

import time
from pywinauto import Application
import win32gui
# 根据应用程序窗口名获得句柄
句柄 = win32gui.FindWindow(None, '微信')
# 通过句柄连接已有微信进程
微信主程序 = Application(backend='uia').connect(handle=句柄)
# 拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
微信窗口.restore()
会话列表 = 微信窗口.child_window(control_type='List', title='会话')
会话 = 会话列表.items()[0]
会话.double_click_input() # 双击会话弹出独立会话框
time.sleep(3)
# 根据ChatWnd 查找到聊天框
聊天窗口 = 微信主程序.window(class_name='ChatWnd')
# 检查窗口是否存在
if 聊天窗口.exists():
聊天窗口.close() #关闭窗口

鼠标操作
pywinauto自带的鼠标操作有些时候并不能完全满足要求,可以调用mouse的方法
导入:

from pywinauto import mouse

鼠标常见操作:

# 移动鼠标
mouse.move(coords=(x, y))
# 指定位置,鼠标左击
mouse.click(button='left', coords=(40, 40))
# 鼠标双击
mouse.double_click(button='left', coords=(140, 40))
# 将属性移动到(140,40)坐标处按下
mouse.press(button='left', coords=(140, 40))
# 将鼠标移动到(300,40)坐标处释放,
mouse.release(button='left', coords=(300, 40))
# 右键单击指定坐标
mouse.right_click(coords=(400, 400))
# 鼠标中键单击指定坐标(很少用的到)
mouse.wheel_click(coords=(400, 400))
# 滚动鼠标 wheel_dist指定鼠标滚轮滑动,正数往上,负数往下。
mouse.scroll(coords=(1200,300),wheel_dist=-3)

以滑动会话列表为例:

from pywinauto import Application, mouse
import win32gui
# 以控件中心为起点,滚动
# distance指定鼠标滚轮滑动,正数往上,负数往下
def mouse_scroll(control, distance):
        rect = control.rectangle()
        cx = int((rect.left+rect.right)/2)
        cy = int((rect.top + rect.bottom)/2)
        mouse.scroll(coords=(cx, cy), wheel_dist=distance)
# 根据应用程序窗口名获得句柄
句柄 = win32gui.FindWindow(None, '微信')
# 通过句柄连接已有微信进程
微信主程序 = Application(backend='uia').connect(handle=句柄)
# 拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
微信窗口.restore()
会话列表 = 微信窗口.child_window(control_type='List', title='会话')
mouse_scroll(会话列表, distance=-3)

键盘操作

首先通过以下命令安装键盘库

pip install keyboard

        和控件自己的type_keys()方法效果一样,但是更快,那个是从前到后依次地输入,通过键盘的操作可以直接粘贴一大段内容。
        所以在发送文件和图片的时候可以使用键盘模块,复制粘贴,比type_keys()的方式速度要快多了,并且该模块也可以适配很多表情等特殊符号。
        Emoji表情对应的Unicode编码可参考:https://articles.zsxq.com/id_0ph9xzpw8ju7.html


from pywinauto import Application
import keyboard
import io
import win32gui
# 根据应用程序窗口名获得句柄
句柄 = win32gui.FindWindow(None, '微信')
# 通过句柄连接已有微信进程
微信主程序 = Application(backend='uia').connect(handle=句柄)
# 拿到微信主窗口
微信窗口 = 微信主程序.window(class_name='WeChatMainWndForPC')
微信窗口.restore()
# \ue415为表情
信息 = '''
道可道,非常道;名可名,非常名。
无名,天地之始,有名,万物之母。
故常无欲,以观其妙,常有欲,以观其徼。
此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。\ue415
'''
消息输入框 = 微信窗口.child_window(control_type='Edit', title='输入')
消息输入框.click_input()
消息输入框.type_keys('^a')
# 方法一逐字输入,无法输入表情
消息输入框.type_keys(信息)
# 方法二 通过键盘 直接粘贴大片字符,可贴表情
for line in io.StringIO(信息):
keyboard.write(line.strip())
keyboard.send('ctrl+enter')
# 发送enter键 发送消息
# keyboard.send('enter')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值