技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)

简介: 技术经验解读:【python自动化】02.pywin32库自动操作键鼠(保姆级代码注释)

目录


源码和工具下载


大漠综合工具->坐标和窗口信息抓取


在你的桌面上新建一个记事本用于后面的代码测试


完整项目源码


实现思路


介绍win32的基础思路


基本步骤


API介绍


代码实战


1. 获取窗口句柄的三种方法


2. 根据窗口句柄获取窗口信息


3. 通过句柄设置窗口


4. 激活窗口


5. 鼠标信息的获取


6. 鼠标点击事件


7. 键盘键位操作


8. 延时等待


9. 剪切板操作


10. 消息框与选择问答


11. 关闭窗口


N. 小结


总结


『python自动化』分享win32gui、cv2、easyocr等库相关的新手入门教程,目标是编写python程序进行自动化办公,解放双手。


欢迎关注 『python自动化』 系列,持续更新中


欢迎关注 『python自动化』 系列,持续更新中


如果安装win32gui库遇到了困难,可以参考下文安装。


【python自动化】01.安装配置库和环境之win32gui安装失败(保姆级图文)


源码和工具下载


大漠综合工具->坐标和窗口信息抓取


大漠综合工具获取句柄和窗口信息


1.用十字标记拖动到需要的窗口(注意拖到大窗口而不是小窗口,是整个记事本窗口而不是记事本的输入区域的小窗口)


2.绑定(方便后续的操作)


3.点击属性即可查看窗口信息,包括窗口的大小、坐标、16进制句柄


我的gitee仓库pywin32库自动操作键鼠


我们一般用的是16进制句柄,在这里查看


坐标和色点采集


注意这里的相对坐标和绝对坐标,我们绑定了窗口后默认把窗口左上角(0,0)视为参考标准。


在你的桌面上新建一个记事本用于后面的代码测试


完整项目源码


下载拿来即用


我的gitee仓库pywin32库自动操作键鼠


实现思路


介绍win32的基础思路


万物皆是窗口,首先获取窗口的句柄,然后再以此为基础对于窗口输送键鼠的命令。


基本步骤


获取窗口句柄->激活窗口->设置窗口大小位置->激活聊天输入框->输入内容


API介绍


下面的代码实战会详细介绍每个方法的参数,也可以访问pywin32的官方文档查看。(建议这么做,因为以后我们自学其他库都要经历查看文档这个过程)


官网网址


代码实战


1. 获取窗口句柄的三种方法


注意窗口类名, 窗口标题名两者必须至少有一个才能找到你想要的窗口,另一个可以缺省为None


法1:win32gui.FindWindow(窗口类名, 窗口标题名)#直接查找窗口


实例:win32gui.FindWindow(“Notepad”, None)


返回值:窗口的16进制句柄


import win32gui


#如果失败,要做好异常处理


#1.根据窗口标题获取句柄,通过标题查找,仅返回一个顶层窗口的句柄,不支持模糊查询


try:


# 获取窗口句柄


handle = win32gui.FindWindow("Notepad", None)#通过窗口标题获取窗口句柄


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


法2:win32gui.FindWindowEx(父窗口句柄, 查找窗口顺序, 窗口类名, 窗口标题名)#根据父窗口查找子窗口


实例:win32gui.FindWindowEx(0, 0, “Notepad”, None)


父窗口句柄:如果为 0,则假定为桌面窗口


查找窗口顺序:子窗口后按Z顺序搜索,可以为0搜索全部


返回值:查找得到的子窗口窗口的16进制句柄


#2.通过父窗口找子窗口,根据窗口类名和标题检索句柄,查找


# 参数


# 家长:PyHANDLE


# 将搜索其子窗口的窗口。如果为 0,则假定为桌面窗口。


# ChildAfter : PyHANDLE


# 子窗口后按Z顺序搜索,可以为0搜索全部


# 类名:PyResourceId


# 要查找的窗口类的名称或原子,可以是 None


# 窗口名称:字符串


# 要查找的窗口标题,可以是 None


import win32gui


try:


# 获取窗口句柄


# handle = win32gui.FindWindowEx(0, 0, "Notepad", '新建文本文档.txt - 记事本')


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)


#注意,当你修改了记事本后标题名字前加上了一个变成了“新建文本文档.txt - 记事本”,所以这里可以填写None缺省,只用类名查找


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


法3:win32gui.WindowFromPoint((窗口x坐标, 窗口y坐标))#根据窗口坐标查找顶层符合坐标要求的一个窗口


实例:win32gui.WindowFromPoint((0, 0))


窗口坐标是每个窗口都会有的属性,但是这个方法只会查找顶层的那一个窗口,所以说改变置顶窗口就会改变通过这个方法获取的窗口句柄,所以不建议用。


返回值:查找得到的子窗口窗口的16进制句柄


#3.根据窗口左上角坐标获取句柄,(0, 0)只获取最顶层的左上角窗口,这种方法我个人不建议使用,因为顶层的窗口变化了,句柄就变化了


import win32gui


try:


# 获取窗口句柄


handle = win32gui.WindowFromPoint((0, 0))


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


2. 根据窗口句柄获取窗口信息


#获取窗口信息 (x,y坐标,还有宽度,高度)


原型:win32gui.GetWindowRect(窗口句柄)


实例:handleMessage = //代码效果参考:http://hnjlyzjd.com/hw/wz_24417.html

win32gui.GetWindowRect(handle)

返回值:handleMessage是一个元组,包含四个元素,结构是(x坐标,y坐标,宽度,高度)


#获取窗口标题


原型:win32gui.GetWindowText(窗口句柄)


实例:win32gui.GetWindowText(handle)


返回值:字符串,窗口标题


#获取窗口类名


原型:win32gui.GetClassName(窗口句柄)


实例:win32gui.GetClassName(handle)


返回值:字符串,窗口类名


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


# 注意窗口信息获取如果失败,要做好异常处理


try:


# 获取窗口信息 (x,y坐标,还有宽度,高度)


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 获取窗口标题


title = win32gui.GetWindowText(handle)


print("窗口标//代码效果参考:http://hnjlyzjd.com/hw/wz_24415.html

题是:{}".format(title))

# 获取窗口类名


class_name = win32gui.GetClassName(handle)


print("窗口类名是:{}".format(class_name))


except Exception as e:


print("窗口信息获取失败:{}".format(e))


3. 通过句柄设置窗口


#设置窗口信息


原型:win32gui.MoveWindow(窗口句柄, 窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新)


实例:win32gui.MoveWindow(handle, 0, 0, 1280, 768, True)


返回值:None


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


except Exception as e:


print("窗口句柄获取失败:{}".format(e))


try:


# 获取窗口信息 (x,y坐标,还有宽度,高度)


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 获取窗口标题


title = win32gui.GetWindowText(handle)


print("窗口标题是:{}".format(title))


# 获取窗口类名


class_name = win32gui.GetClassName(handle)


print("窗口类名是:{}".format(class_name))


# 设置窗口


# 参数:句柄,窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新


win32gui.MoveWindow(handle, 0, 0, 1280, 768, True)


# 设置窗口后获取窗口信息,查看是否设置成功


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("修改窗口后的窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


except Exception as e:


print("窗口信息获取失败:{}".format(e))


4. 激活窗口


#激活窗口


原型:win32gui.SetForegroundWindow(窗口句柄)


实例:win32gui.SetForegroundWindow(handle)


返回值:None


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


# 将创建指定窗口的线程设置到前台,并且激活该窗口


win32gui.SetForegroundWindow(handle)


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


5. 鼠标信息的获取


#获取鼠标位置


原型:win32api.GetCursorPos()


实例:point_position = win32api.GetCursorPos()


返回值:point_position 是一个元组,结构是(x坐标,y坐标)


#设置鼠标位置


原型:win32api.SetCursorPos((x坐标,y坐标))


实例:win32api.SetCursorPos((0, 0))


返回值:None


import win32gui


import win32api


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("鼠标位置是:{}".format(point_position))


# 设置鼠标位置


win32api.SetCursorPos((0, 0))


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("设置后鼠标位置是:{}".format(point_position))


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


6. 鼠标点击事件


鼠标点击分为点击和弹起2个过程。


#按下鼠标左键


原型:win32api.mouse_event(键位操作, 0, 0)


实例:win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)


返回值:None


#松开鼠标左键


原型:win32api.mouse_event(键位操作, 0, 0)


实例:win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)


参数解读(dwFlags ,dx ,dy ,dwData ,dwExtraInfo)


dwFlags=0:双字,指定各种功能选项的标志


dx:double类型,鼠标的水平位置


dy : double类型,鼠标的垂直位置


dwData:double类型,标志特定参数


dwExtraInfo=0:double类型,与鼠标事件相关的附加数据


返回值:None


#键位表


MOUSEEVENTF_LEFTDOWN:表明接按下鼠标左键


MOUSEEVENTF_LEFTUP:表明松开鼠标左键


MOUSEEVENTF_RIGHTDOWN:表明按下鼠标右键


MOUSEEVENTF_RIGHTUP:表明松开鼠标右键


MOUSEEVENTF_MIDDLEDOWN:表明按下鼠标中键


MOUSEEVENTF_MIDDLEUP:表明松开鼠标中键


MOUSEEVENTF_WHEEL:鼠标轮移动,数量由data给出


import win32api


import win32con


import win32gui


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#


print("窗口句柄是:{}".format(handle))


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("鼠标位置是:{}".format(point_position))


# 模拟鼠标在(1000, 500)位置进行点击操作


point = (1000, 500)


win32api.SetCursorPos(point)


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)#按下鼠标左键


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)#松开鼠标左键


# 获取鼠标位置


point_position = win32api.GetCursorPos()


print("鼠标位置是:{}".format(point_position))


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


7. 键盘键位操作


键盘操作类似鼠标也分为按下和弹起2个过程。


有所区别的是,如果要输入内容,要先让鼠标激活输入框的焦点,所以要先点击一下。


同时也要注意一点,窗口操作最好加入一些延时,避免时序错误,导致出现先输入再激活焦点的错误,从而导致无法输入。


#按下按键


原型:win32api.keybd_event(键码, 硬件扫描码, 按下还是弹起的标志位, 与击键相关的附加的32位值)


实例:win32api.keybd_event(65, 0, KEYEVENTF_EXTENDEDKEY, 0)#按下A


实例:win32api.keybd_event(65, 0, 0, 0)#按下A


返回值:None


#弹起按键


原型:win32api.keybd_event(键码, 硬件扫描码, 按下还是弹起的标志位, 与击键相关的附加的32位值)


实例:win32api.keybd_event(65, 0, win32con.KEYEVENTF_KEYUP, 0)#松开A


实例:win32api.keybd_event(65, 0, 1, 0)#松开A


返回值:None


bVk:虚拟键码


bScan:硬件扫描码,一般设置为0即可


dwFlags:函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP(也就是1)则该按键被释放


dwExtraInfo:定义与击键相关的附加的32位值,一般设置为0即可


import win32gui


import win32api


import win32con


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#桌面窗口的所有子窗口检索类名"Edit",标题为None的窗口


print("窗口句柄是:{}".format(handle))


# 设置窗口


# 参数:句柄,窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新


win32gui.MoveWindow(handle, 0, 0, 500, 500, True)


# 设置窗口后获取窗口信息,查看是否设置成功


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("修改窗口后的窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 将创建指定窗口的线程设置到前台,并且激活该窗口


win32gui.SetForegroundWindow(handle)


#加入延时,否则可能会操作失败


print("如果没有下面以这一行代码,可能无法正常输入A B 字母,这就是延时等待的作用")


win32api.Sleep(1000)


#激活窗口输入栏


# 模拟鼠标在(246,217)位置进行点击操作,这个坐标主要是点击一下txt记事本的输入窗口,激活焦点


point = (246,217)


win32api.SetCursorPos(point)


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)#按下鼠标左键


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)#松开鼠标左键


#加入延时,否则可能会操作失败


win32api.Sleep(1000)


#在记事本中输入A B 字母


win32api.keybd_event(65, 0, 0, 0)#按下A


win32api.keybd_event(66, 0, 0, 0)#按下B


win32api.keybd_event(65, 0, win32con.KEYEVENTF_KEYUP, 0)#松开A


win32api.keybd_event(66, 0, win32con.KEYEVENTF_KEYUP, 0)#松开B


except Exception as e:


print("窗口句柄获取失败或是前台设置失败:{}".format(e))


8. 延时等待


这一节的内容和第7节类似,就是让大家试试看,如果不加入延时会发生什么,强调一下延时的作用。


#延时等待


原型:win32api.Sleep(等待毫秒)


实例:win32api.Sleep(1000)


返回值:None


import win32gui


import win32api


import win32con


# 注意窗口句柄获取如果失败,要做好异常处理


try:


# 获取窗口句柄


handle = win32gui.FindWindowEx(0, 0, "Notepad", None)#桌面窗口的所有子窗口检索类名"Edit",标题为None的窗口


print("窗口句柄是:{}".format(handle))


# 设置窗口


# 参数:句柄,窗口左边界,窗口上边界,窗口宽度,窗口高度,确定窗口是否被刷新


win32gui.MoveWindow(handle, 0, 0, 500, 500, True)


# 设置窗口后获取窗口信息,查看是否设置成功


handleMessage = win32gui.GetWindowRect(handle)#通过窗口句柄获取窗口信息


print("修改窗口后的窗口 x,y坐标,还有宽度,高度是:{}".format(handleMessage))


# 将创建指定窗口的线程设置到前台,并且激活该窗口


win32gui.SetForegroundWindow(handle)


#加入延时,否则可能会操作失败


print("如果没有下面以这一行代码,可能无法正常输入A B 字母,这就是延时等待的作用")


win32api.Sleep(1000)


#激活窗口输入栏


# 模拟鼠标在(246,217)位置进行点击操作


point = (246,217)


win32api.SetCursorPos(point)


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)#按下鼠标左键


win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)#松开鼠标左键


#加入延时,否则可能会操作失败


print("如果没有下面以这一行代码,可能无法正常输入A B 字母,这就是延时等待的作用")


win32api.Sleep(1000)


#在记事本中输入A B 字母


win32api.keybd_event(65, 0, 0, 0)#按下A


win32api.keybd_event(66, 0, 0, 0)#按下B


win32api.keybd_event(65, 0, win32con.KEYEVENTF_KEYUP, 0)#松开A


win32api.keybd_event(66, 0, win32con.KEYEVENTF_KEYUP, 0)#松开B


except Exception as e:


print("错误:{}".format(e))


9. 剪切板操作


#打开剪切板


原型:win32clipboard.OpenClipboard()


实例:win32clipboard.OpenClipboard()


返回值:None


#剪切板置空


原型:win32clipboard.EmptyClipboard()


实例:win32clipboard.EmptyClipboard()


置剪切板为空,赋初始值是程序员的好习惯,注意任何数据一开始的样子


返回值:None


相关文章
|
2天前
|
机器人 API 开发者
Python基于Mirai开发的QQ机器人保姆式教程(亲测可用)
Python基于Mirai开发的QQ机器人保姆式教程(亲测可用)
|
2天前
|
测试技术
Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)
Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)
|
3天前
|
Linux 数据处理 C语言
经验大分享:python3使用libpcap库进行抓包及数据处理
经验大分享:python3使用libpcap库进行抓包及数据处理
|
1月前
|
Python
办公自动化-Python如何提取Word标题并保存到Excel中?
办公自动化-Python如何提取Word标题并保存到Excel中?
52 2
|
4天前
|
XML 测试技术 数据格式
软件测试之 自动化测试 基于Python语言使用Selenium、ddt、unitTest 实现自动化测试(下)
软件测试之 自动化测试 基于Python语言使用Selenium、ddt、unitTest 实现自动化测试(下)
10 3
|
4天前
|
Java 测试技术 程序员
软件测试之 自动化测试 基于Python语言使用Selenium、ddt、unitTest 实现自动化测试(上)
软件测试之 自动化测试 基于Python语言使用Selenium、ddt、unitTest 实现自动化测试(上)
14 1
|
14天前
|
运维 监控 API
自动化运维实践指南:Python脚本优化服务器管理任务
本文探讨了Python在自动化运维中的应用,介绍了使用Python脚本优化服务器管理的四个关键步骤:1) 安装必备库如paramiko、psutil和requests;2) 使用paramiko进行远程命令执行;3) 利用psutil监控系统资源;4) 结合requests自动化软件部署。这些示例展示了Python如何提升运维效率和系统稳定性。
30 8
|
16天前
|
数据采集 人工智能 数据挖掘
让工作自动化起来!无所不能的Python
让工作自动化起来!无所不能的Python
|
24天前
|
JSON 程序员 数据格式
豆瓣评分9.6!用81个项目带你从Python 3零基础到Python自动化
Python的名字来自超现实主义的英国喜剧团体,而不是来自蛇。Python程序员被亲切地称为Pythonistas。Monty Python和与蛇相关的引用常常出现在Python的指南和文档中。
|
26天前
|
数据采集 JSON API
自动化Reddit图片收集:Python爬虫技巧
自动化Reddit图片收集:Python爬虫技巧