当前位置:   article > 正文

Python键鼠控制·PyAutoGui库_pyautogui.dragrel

pyautogui.dragrel

日常使用计算机,命令行程序可以说是为批量操作文件而生,但作为普通用户,最多的还是通过鼠标键盘操作形形色色的图形界面程序。试想下面一个场景:有成千上万个文件,都需要通过图形界面进行同样的一套编辑、保存工作,靠手工一遍一遍地重复做,累死人不说,时间久了必然出现错误,作为程序猿,怎么能忍重复3次以上的工作,必须利用程序自动化。要想图形界面也能像命令行程序那样精确控制,就需要GUI自动化工具了。不得不赞Python生态之丰富,GUI自动化自动化工具也有多种库可选,比如Windows平台的pywin32,以及本文主角——跨平台的PyAutoGUI

目录

01. PyAutoGUI简介

02.PyAutoGUI使用入门

安装

快速上手

1. 通用功能

 2. 鼠标控制

3. 键盘控制

4. 消息窗口

03.任务示例

参考


01. PyAutoGUI简介

pywin32直接包装了几乎所有的Windows API,可以方便地从Python直接调用,把Windows API按照功能分了一些大类,每一个大类作为一个模块,常见如win32apiwin32guiwin32com等,其中win32com使用微软独门的COM接口技术进行进程间通信,可以实现控制GUI程序。但前提是,这些程序得支持COM接口。win32api则更加原始,完全通过Win32 API调用获得/生成窗口句柄、发送消息事件,十分繁琐。

PyAutoGUI的思路与此完全不同,它是接管了鼠标、键盘使用权,基本上完全照搬人的操作,底层不必套牢在Windows系统,没错,它是跨平台的。官网地址:https://github.com/asweigart/pyautogui。原本,这类GUI自动化工具的初衷是给GUI程序自动化测试用,产生点击鼠标、敲击键盘的行为,在日志中记录下消息事件和GUI程序的响应结果,事后分析GUI程序可能存在的bug。不过,既然能产生点击鼠标、敲击键盘的行为,我们就可以用来控制GUI程序批量完成文件编辑、保存工作。

按照官方的说法,PyAutoGUI给人类用的GUI自动化神器,简单高效、函数分类清晰,它被awesome-pythonawesome-python-cn收录。

02.PyAutoGUI使用入门

安装

推荐通过pip安装,一行命令搞定。

python -m pip install -U pyautogui

PyAutoGUI依赖于pyscreezepymsgboxpytweening,上述命令会自动安装这3个库。安装完成后可以发现,在site-packages\pyautogui有6个文件,名字带java、osx、win、x11的是在不同平台的实现方案,再在__init__.py__main__.py中检测当前系统平台进行封装。其中,java平台的实现文件为空,猜测是未来计划支持的,先占个坑。

  1. __init__.py
  2. __main__.py
  3. _pyautogui_java.py # 空文件,猜测是未来支持
  4. _pyautogui_osx.py
  5. _pyautogui_win.py
  6. _pyautogui_x11.py

快速上手

PyAutoGUI设计简洁,相关符号经过内部import之后,被封装在pyautogui单个模块中,因此Python程序中只要import pyautogui之后便可通过.符号访问pyautogui中的函数、变量。pyautogui中函数大致分为通用功能、鼠标控制、键盘控制、消息窗口、截图5大类。

1. 通用功能

  1. import pyautogui
  2. a = pyautogui.size() # 获取屏幕尺寸(分辨率×分辨率)
  3. print(a)
  4. #输出:Size(width=1920, height=1080)
  5. a = pyautogui.position() # 获取鼠标当前位置
  6. print(a)
  7. #输出:Point(x=960, y=540)
  8. a = pyautogui.onScreen(100,200) # 判断坐标是否在屏幕范围内
  9. print(a)
  10. #输出:True
  11. a = pyautogui.onScreen(100,2000) # 判断坐标是否在屏幕范围内
  12. print(a)
  13. #输出:False

坐标体系至关重要,后续鼠标位置、图片大小都根据这套体系定义。PyAutoGUI沿用了传统的坐标体系,并未重新定义,如下图所示。x的取值范围是[0, 宽度分辨率-1],y的取值范围是[0, 高度分辨率-1]。 

 2. 鼠标控制

鼠标移动,包括绝对位置移动和相对位置移动。

  1. import pyautogui
  2. x,y = pyautogui.size() # 保存屏幕尺寸
  3. # 绝对位置移动,移动至屏幕正中心,鼠标移动过渡时间duration设为1秒
  4. pyautogui.moveTo(x/2,y/2,duration = 1)
  5. # 相对位置移动,向右100、向上200,鼠标移动过渡时间duration设为0.5秒
  6. pyautogui.moveRel(100, -200, duration = 0.5)

鼠标点击,一个click()函数把点鼠标的活包干,过程也可分解为mouseDown()mouseUp();另有在click()之上封装的rightClick()middleClick()doubleClick()tripleClick()等函数。鼠标点击之前允许指定要移动的目标位置,若目标位置不在运行当前Python程序的终端/IDE范围内,则可能对其他GUI程序触发鼠标点击事件,从而引起其响应,即焦点移动至其他GUI程序。

  1. # 移动至屏幕中心点击一下左键,过渡时间0.5秒
  2. pyautogui.click(x/2,x/2, duration=0.5)
  3. # 不指定x、y,在当前位置点击一下右键
  4. pyautogui.click(button = 'right')
  5. # 移动至(100,100)点击3次左键,点击间隔0.1s,鼠标移动过渡时间0.5秒
  6. pyautogui.click(100,100, clicks = 3,interval = 0.1,duration = 0.5)
  7. # 移动至(100,100)点击2次右键,点击间隔0.5s,鼠标移动过渡时间0.2秒
  8. pyautogui.click(100,100, clicks = 2,interval = 0.5,button =' right',duration = 0.2)

滚动鼠标滚轮。

  1. # 鼠标位置不动,向上回滚2个单位,项目文档对滚动量参数说明不详
  2. pyautogui.scroll(2)
  3. # 鼠标移动至(1000,700),前下滚动10个单位
  4. pyautogui.scroll(-10,1000,700)
  5. # 运行发现鼠标并没有动

鼠标拖曳,指从当前位置按下鼠标,移动至目标位置再释放的过程,指定目标位置同样有绝对位置和相对位置两种方式,和移动鼠标函数很像。另外,试用下来,未发现drag()函数和dragRel()的差异。

  1. # 将鼠标从当前位置拖至屏幕中心,默认左键
  2. pyautogui.dragTo(x/2,x/2)
  3. # 将鼠标从当前位置向左100像素、向右200像素拖动,过渡时间0.5秒,指定右键
  4. pyautogui.dragRel(-100,200,duration = 0.5,button = 'right')

3. 键盘控制

控制按键,也是一个press()函数基本把活包干,按键动作往细分解包含keyDown()keyUp()两个过程;在此基础上封装,有typewrite()hotkey()两个高阶一点的函数,分别用于输入字符串和按快捷键。

  1. # 键名用字符串表示,支持的所有键名,存在pyautogui.KEYBOARD_KEYS变量中,包括26个字母、数字、符号、F1~F20、方向等等所有按键
  2. pyautogui.press('a') # 按字母A键,字母支持大小写
  3. # 程序向终端输入了字符a,若程序运行时输入法为中文状态,由于没有继续输入空格或回车,输入法仅列出候选字,并不会输入到终端
  4. 打字输出:a
  5. # 传入键名列表(按键p、按键y、空格),按键之间间隔0.1秒(默认0)
  6. pyautogui.press(['p','y','space'], interval = 0.1)
  7. # 运行前将输入法切换到中文状态,往终端直接输入了“便宜”
  8. 打字输出:便宜
  9. # typewrite方式一:传入字符串,不支持中文字符,因为函数无法知道输入法需要什么按键才能得到中文字符
  10. pyautogui.typewrite('hello,\n PyAutoGUI')
  11. # 程序把字符串"'hello, PyAutoGUI!"和换行符输入到了终端
  12. 打字输出:hello,
  13. PyAutoGUI
  14. # typewrite方式二:传入键名列表,按键之间间隔0.1秒(默认0)
  15. pyautogui.typewrite(['s','r','f','space'], interval=0.1)
  16. # 运行前将输入法切换到中文状态,往终端直接输入了“输入法”3个字
  17. 打字输出:输入法
  18. # 大小写字母是自动支持的,仍然尝试一次切换到大写
  19. pyautogui.typewrite(['capslock','p','y'])
  20. # CapsLock按键灯被点亮,程序往终端输入了"PY"
  21. 打字输出:PY
  22. # hotkey屏蔽了需要反复keyDown、keyUp的细节,参数是任意个键名,而非列表
  23. pyautogui.hotkey('ctrl', 'shift', 'esc') #调出任务管理器
  24. pyautogui.hotkey('alt','ctrl','delete') #调出重启界面,但运行未调出

4. 消息窗口

PyAutoGUI利用pymsgbox的功能,以JavaScript风格函数提供消息框功能,包括alert()confirm()prompt() 、password(),连参数都是一致的,熟悉JavaScript的朋友不会陌生。

  1. import pyautogui
  2. a = pyautogui.alert(text = '警告',title = 'PyAutoGUI消息框',button = 'OK')
  3. print(a)
  4. 输出: OK # 点击的按键被返回

  1. a = pyautogui.confirm(text = '请选择',title = 'PyAutoGUI消息框',buttons = ['1','2','3'])
  2. print(a)
  3. 输出:2 #选择的按键被返回

 

  1. a = pyautogui.prompt(text='请输入',title='PyAutoGUI消息框',default='请输入')
  2. print(a)
  3. 输出:by anou.

  1. a = pyautogui.password(text = '输入密码',title = 'PyAutoGUI消息框',default = '',mask = '*')
  2. 输出:anmou.

03.任务示例

前文只是PyAutoGUI相关函数的说明,要真正熟悉它,必须结合具体任务。现有这样一个任务,成千上万个CAD图分布在几十个文件夹中,需要对每个图进行编辑操作,假使这个操作就是简单旋转下视角,再保存。AutoCAD程序本身是有脚本功能的,因此可以利用AutoCAD来完成本任务,综合考虑以下原因促使我转向PyAutoGUI的路线上来:

  1. AutoCAD是商业软件,本人希望尽可能地减少对商业软件的依赖;
  2. AutoCAD的脚本功能十分有限,没有循环,难以适应如此多数量的文件操作,而且去熟悉AutoCAD脚本可能比PyAutoGUI更花时间;
  3. 利用PyAutoGUI熟悉GUI控制后,可以套在别的GUI程序上,未来仍有使用价值,如果使用AutoCAD则始终被限定在AutoCAD的操作范围内,价值低,而且与第一条相悖。

决定走PyAutoGUI的路线,做了如下工作:

  1. 找到另一个轻量看图软件,支持简单的编辑功能,正好包括旋转视角;
  2. 手工操作键盘鼠标,利用这个看图软件完成1个文件的编辑、保存流程;
  3. 将涉及操作的菜单、按钮等截图保存起来备用,将上述流程代码化,落地成果就是1个操作函数;
  4. 由于看图软件应需要时间,移动、点击鼠标等操作的过渡时间需要调试确定;
  5. 完成1个文件的操作流程后,在主函数编写文件匹配、循环等功能,在循环中调用操作函数,初期只拿10个文件批量操作,调试无误后,主函数的文件匹配修改为整个文件夹,包含成千上万个文件。

操作函数代码。

  1. import os
  2. import pyautogui as pag
  3. __sizex__, __sizey__ = pag.size() #获得屏幕尺寸
  4. def cad_turn(cad_file, outd):
  5. '''
  6. cad_file : 要操作的CAD文件
  7. outd : 文件输出路径
  8. '''
  9. c = pag.locateCenterOnScreen(__icon_open__, region=(0,0,__sizex__/10,__sizey__/20) ) # 打开图标,图标事先截图保存
  10. pag.moveTo(*c, duration=0.05)
  11. pag.click( button="left") # 点击打开按钮
  12. pag.moveRel(__sizex__/4, __sizey__/4) # 确保文件打开窗口获得焦点
  13. pag.typewrite(message=cad_file,interval=0.1) # 输入文件路径
  14. pag.press('enter')
  15. c = pag.locateCenterOnScreen(__icon_view__, region=(__sizex__/4, 0,__sizex__/2, __sizey__/10) ) # 旋转视图图标
  16. pag.moveTo(*c, duration=2)
  17. pag.click(clicks=7, interval=1, button="left") # 点击旋转视角按钮
  18. c = pag.locateCenterOnScreen(__icon_saveas__, region=(0, 0, __sizex__/10, __sizey__/20) ) # 另存为图标
  19. pag.moveTo(*c, duration=0.2)
  20. pag.click( button="left") # 点击另存为按钮
  21. pag.moveRel(__sizex__/4, __sizey__/4) # 确保文件打开窗口获得焦点
  22. pag.typewrite(message=os.path.join(out, fbase+'-se'), interval=0.1) # 输入保存路径
  23. pag.press('enter')
  24. # 关闭所有可能存在的窗口,避免占用太多内存
  25. while( True ):
  26. try :
  27. pag.moveTo(__sizex__/2, __sizey__/2, duration=0.3) # 延时
  28. c = pag.locateCenterOnScreen(__icon_close__, region=(__sizex__/5, 0, __sizex__*3/5, __sizey__/20) )
  29. pag.moveTo(*c, duration=0.1) # 移到“x”按钮
  30. pag.click( button="left") # 点击“x”按钮
  31. except TypeError:
  32. break

主函数代码。

  1. if __name__ == "__main__":
  2. p = r'x/y/z/CAD文件所在路径'
  3. cad_src = glob_file_list( p, r"*.DXF") # 匹配出要操作的文件
  4. total = len(cad_src)
  5. if(total == 0):
  6. print('无文件需处理,退出...')
  7. try:
  8. for idx,x in enumerate(cad_src, start=1):
  9. print("[{}/{}] 处理{}...".format(idx, total, x))
  10. cad_turn(x, "out")
  11. except Exception as e:
  12. print("错误:{}".format(e))

开启看图软件,输入法切换到英文状态,再运行Python程序。

04.拓展

PyAutoGui仅支持控制键鼠,想要检测键鼠,需要另一个库PyHook3

安装

安装过程较复杂 建议查看我的另一篇博文

Python小白·暗某人的博客:PyHook3安装(亲测有用)

实例

相关文章:

At5uto的博文:PyHook3简明教程

  1. import pythoncom
  2. import PyHook3
  3. hm = PyHook3.HookManager()
  4. # 鼠标事件处理函数
  5. def OnMouseEvent(event):
  6. print('MessageName:',event.MessageName) #事件名称
  7. print('Message:',event.Message) #windows消息常量
  8. print('Time:',event.Time) #事件发生的时间戳
  9. print('Window:',event.Window) #窗口句柄
  10. print('WindowName:',event.WindowName) #窗口标题
  11. print('Position:',event.Position) #事件发生时相对于整个屏幕的坐标
  12. print('Wheel:',event.Wheel) #鼠标滚轮
  13. print('Injected:',event.Injected) #判断这个事件是否由程序方式生成,而不是正常的人为触发。
  14. print('---')
  15. # 返回True代表将事件继续传给其他句柄,为False则停止传递,即被拦截
  16. return True
  17. #键盘事件处理函数
  18. def OnKeyboardEvent(event):
  19. print('MessageName:',event.MessageName) #同上,共同属性不再赘述
  20. print('Message:',event.Message)
  21. print('Time:',event.Time)
  22. print('Window:',event.Window)
  23. print('WindowName:',event.WindowName)
  24. print('Ascii:', event.Ascii, chr(event.Ascii)) #按键的ASCII码
  25. print('Key:', event.Key) #按键的名称
  26. print('KeyID:', event.KeyID) #按键的虚拟键值
  27. print('ScanCode:', event.ScanCode) #按键扫描码
  28. print('Extended:', event.Extended) #判断是否为增强键盘的扩展键
  29. print('Injected:', event.Injected)
  30. print('Alt', event.Alt) #是某同时按下Alt
  31. print('Transition', event.Transition) #判断转换状态
  32. print('---')
  33. # 同上
  34. return True
  35. #绑定事件处理函数
  36. hm.MouseAllButtonsDown = OnMouseEvent #将OnMouseEvent函数绑定到MouseAllButtonsDown事件上
  37. hm.KeyDown = OnKeyboardEvent #将OnKeyboardEvent函数绑定到KeyDown事件上
  38. hm.HookMouse() #设置鼠标钩子
  39. hm.HookKeyboard() #设置键盘钩子
  40. pythoncom.PumpMessages()

参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/121100
推荐阅读
相关标签
  

闽ICP备14008679号