python中spy++的使用超详细教程


Posted in Python onJanuary 29, 2021

1、spy++的基本操作

python中spy++的使用超详细教程 

1.1 窗口属性查找

python中spy++的使用超详细教程

拖住中间的“寻找工具”放到想要定位的软件上,然后松开

python中spy++的使用超详细教程

以微信为例,我们会得到“微信”这个窗口的句柄,为“00031510”,注意这个句柄是“十六进制”,即“0x31510”。

python中spy++的使用超详细教程

点击ok我们会看到更详细的属性信息

python中spy++的使用超详细教程 

1.2 窗口spy++定位

python中spy++的使用超详细教程

同理拖放到“微信”上,获取到“微信”的界面

python中spy++的使用超详细教程

点击ok,会直接定位到“微信”

python中spy++的使用超详细教程

在这里我们会看到一条信息00031510 “微信” WeChatMainWndForPC
? 00031510:代表十六进制的窗口句柄
? 微信:代表窗口标题
? WeChatMainWndForPC:代表窗口的类名


2、python结合spy++

导入必要的库

import win32con
from win32 import win32gui
from win32 import win32clipboard as w
import pyautogui
import sys

2.1 获取窗口全部属性

def show_window_attr(hwnd):
 """
 显示窗口的属性
 :param hwnd: 窗口句柄(十进制)
 :return: 所有的属性
 WindowName: 窗口标题
 ClassName: 窗口类名
 HwndPy: 窗口句柄(十进制)
 HwndSpy: 窗口句柄(十六进制)
 """
 if not hwnd:
 return
 WindowName = win32gui.GetWindowText(hwnd)
 ClassName = win32gui.GetClassName(hwnd)
 HwndPy = hwnd
 HwndSpy = hex(hwnd)
 return (WindowName, ClassName, HwndPy, HwndSpy)

已经知道“微信”十六进制的窗口句柄,先转化为十进制,可获取全部属性

>>> int(0x31510)
202000
>>> show_window_attr(202000)
('微信', 'WeChatMainWndForPC', 202000, '0x31510')

2.2 获取全部顶层窗口

def show_top_windows():
 """
 列出所有的顶级窗口及属性
 :return: 全部的顶层窗口及对应属性
 """
 hwndList = []
 win32gui.EnumWindows(lambda hwnd, param: param.append(show_window_attr(hwnd)), hwndList)
 return hwndList

获取到的是整个桌面所有的窗口

python中spy++的使用超详细教程

>>> show_top_windows()
[('CClipboardThread', 'CClipboardThread', 2165890, '0x210c82'), ('G', 'GDI+ Hook Window Class', 463410, '0x71232'), ('', 'ForegroundStaging', 66338, '0x10322'), ('', 'ForegroundStaging', 66294, '0x102f6'), ('', 'tooltips_class32', 66234, '0x102ba'), ('', 'tooltips_class32', 66204, '0x1029c'), ('', 'tooltips_class32', 66200, '0x10298'), ('', 'tooltips_class32', 66196, '0x10294'), ('', 'tooltips_class32', 66192, '0x10290'), ('', 'tooltips_class32', 66174, '0x1027e'), ('', 'tooltips_class32', 66166, '0x10276'), ('', 'tooltips_class32', 66154, '0x1026a'), ('', 'tooltips_class32', 66888, '0x10548'), ('', 'tooltips_class32', 131762, '0x202b2'), ('', 'Q360NetmonClass', 197502, '0x3037e'), ('', 'tooltips_class32', 66208, '0x102a0'), ('', 'tooltips_class32', 11404742, '0xae05c6'), ('', 'tooltips_class32', 66214, '0x102a6'), ('', 'tooltips_class32', 66228, '0x102b4'), ('', 'tooltips_class32', 66222, '0x102ae'),

2.3 模糊查找主窗体

def FindFuzzyTopWindow(FuzzyWindowName=None):
 """
 根据标题模糊查找全部符合条件的主窗体
 :param FuzzyWindowName: 窗口标题部分文字
 :return:
 """
 all_windows = show_top_windows()
 result = []
 for window in all_windows:
 if FuzzyWindowName in window[0]:
 result.append(window)
 return result
  • 有时候我们需要通过“部分名称”来找出主窗体的属性
  • 找出了窗体标题含有“同花顺”的全部窗体
>>> FindFuzzyTopWindow(FuzzyWindowName='同花顺')
[('同花顺(v8.80.80) - 我的板块', 'Afx:400000:b:10003:6:d60ca7',
 134184, '0x20c28'), ('同花顺股灵通', '#32770', 462652, '0x70f3c')]

2.4 获取目标父窗体下的全部子窗体

def FindSubHandles(pHandle=None, ClassName=None, WinName=None, index=None):
 """
 返回窗体下全部的子窗体,默认主窗体下的窗体
 :param pHandle: 窗口句柄(十进制)
 :param ClassName: 窗口类名,返回特定类名
 :param WinName: 窗口标题,返回特定标题
 :param index: 位置,返回特定位置的窗口
 :return: 包含属性的全部子窗口
 """
 num = 0
 handle = 0
 SubHandlesList = []
 while True:
 # find next handle, return HwndPy
 handle = win32gui.FindWindowEx(pHandle, handle, ClassName, WinName) 
 if handle == 0:
 # no more handle
 break
 # get handle attribution
 attr = show_window_attr(handle)
 # append to list
 SubHandlesList.append(tuple(list(attr) + [num]))
 num += 1
 if index is not None:
 return SubHandlesList[index]
 else:
 return SubHandlesList
  • 以刚刚“同花顺”为例,十进制句柄为134184
  • 其他参数在特定场合下会起作用
>>> FindSubHandles(pHandle=134184)
[('', 'Button', 69090, '0x10de2', 0), 
('', 'ToolbarWindow32', 69272, '0x10e98', 1),
 ('', 'msctls_statusbar32', 265490, '0x40d12', 2), 
 ('', 'msctls_statusbar32', 134664, '0x20e08', 3), 
 ('', 'AfxFrameOrView42s', 134212, '0x20c44', 4), 
 ('', 'AfxControlBar42s', 134180, '0x20c24', 5), 
 ('', 'AfxControlBar42s', 134192, '0x20c30', 6), 
 ('功能树', 'AfxControlBar42s', 134194, '0x20c32', 7),
 ('', 'AfxControlBar42s', 134196, '0x20c34', 8), 
 ('HqEmbededTradeContainer', 'Afx:400000:0', 69270, '0x10e96', 9), 
 ('功能树', 'Afx:400000:8:10003:10006e:0', 69320, '0x10ec8', 10), 
 ('', 'Afx:400000:0', 69430, '0x10f36', 11), 
 ('', 'Afx:400000:0', 69432, '0x10f38', 12)]

对比SPY++中的结果完全一致

python中spy++的使用超详细教程 

2.5 获取某个父窗口

下面全部的子窗口,遍历所有窗口 这里获取到的是全部层级的子窗口

def ShowAllHandle(pHandle=None, HandleList=[[None]], HandleDict=dict()):
 """
 生成窗口全部对应的关系
 :param pHandle: 目标父窗口
 :param HandleList: 默认为[[None]]
 :param HandleDict: 用于存放对应关系
 :return: 返回目标窗口下全部子父窗口的字典
 """
 sys.setrecursionlimit(1000000)
 if pHandle:
 HandleList[-1][0] = pHandle
 handles = FindSubHandles(HandleList[-1][0][2])
 else:
 handles = FindSubHandles()
 for handle in handles:
 HandleDict[handle] = pHandle
 # 这个根节点已经遍历完,删除
 del HandleList[-1][0]
 # 如果有叶节点,非空,则加入新的叶节点
 if handles:
 HandleList.append(handles)
 # 删除已被清空的根
 HandleList = [HandleGroup for HandleGroup in HandleList if HandleGroup]
 # 如果还有根就继续遍历,否则输出树
 if HandleList:
 return ShowAllHandle(pHandle=HandleList[-1][0], HandleList=HandleList, HandleDict=HandleDict)
 else:
 return HandleDict

pHandle:这个参数设置为

('同花顺(v8.80.80) - 我的板块', 'Afx:400000:b:10003:6:d60ca7', 134184, '0x20c28')

调用函数

ShowAllHandle(FindFuzzyTopWindow(FuzzyWindowName='同花顺')[0])

得到一个全部对应关系的字典

python中spy++的使用超详细教程 

2.6 找到特定窗口的路径

因为句柄在不同电脑上的结果是不同的,所以我们要找到这个唯一的路

def FindHandlePath(TargetHandle, num):
 """
 寻找特定窗口的寻找路径
 :param TargetHandle: 窗口句柄(十六进制)
 :param num: 窗口所属index,在spy++内查看
 :return:
 ParentWindow:顶层窗口
 TargetPath:路径的index
 """
 AllPath = ShowAllHandle(pHandle=None, HandleList=[[None]], HandleDict=dict())
 key = tuple(list(show_window_attr(int(TargetHandle))) + [num])
 handlepath = [key]
 while True:
 key = AllPath[key]
 if not key:
 handlepath = handlepath[::-1]
 ParentWindow = handlepath[0]
 TargetPath = [(i[-1]) for i in handlepath[1:]]
 return ParentWindow, TargetPath
 handlepath.append(key)
  • 逻辑是找到全部层级的对应关系,然后反向搜索
  • 以“同花顺”的“买入”按钮为例,通过SPY++查找

python中spy++的使用超详细教程

我们得到其十六进制句柄为“0x40D98”,同时index为6

python中spy++的使用超详细教程

  • TargetHandle=0x40D98, num=6
  • 获取路径如下
>>> FindHandlePath(TargetHandle=0x40D98, num=6)
(('同花顺(v8.80.80) - 我的板块', 'Afx:400000:b:10003:6:d60ca7', 134184, '0x20c28', 308), 
[5, 0, 6])
  • 主窗体:同花顺(v8.80.80) - 我的板块
  • 5:第6个子窗体
  • 0:第1个子窗体
  • 6:第7个子窗体

2.7 根据路径来查找某个特定窗口的句柄

def FindTargetHandle(pHandle, WindowList):
 """
 递归寻找子窗口的句柄
 :param pHandle: 祖父窗口的完整句柄 (WindowName, ClassName, HwndPy, HwndSpy)
 :param WindowList: 子窗口列表
 :return: 目标窗口的完整属性
 """
 for i in range(len(WindowList)):
 pHandle = FindSubHandles(pHandle[2], index=WindowList[i])
 return pHandle
  • 现在
  • 我们已经有了某个窗体的查找路径,通过上述函数来查找其句柄我们的路径是:(('同花顺(v8.80.80) - 我的板块', 'Afx:400000:b:10003:6:d60ca7', 134184, '0x20c28', 308), [5, 0, 6])
  • 调用函数
>>> FindTargetHandle(('同花顺(v8.80.80) - 我的板块', 'Afx:400000:b:10003:6:d60ca7', 134184, '0x20c28', 308), [5, 0, 6])
('', 'Button', 265624, '0x40d98', 6)
  • 获得到了名为“Button”的窗体
  • 对比我们刚刚的结果,是正确的。

 2.8 根据句柄定位窗体

  • 这个按钮的十进制句柄为:265624
  • 调用函数GetWindowRect
>>> x,y,m,n = win32gui.GetWindowRect(265624)
>>> pyautogui.moveTo((x+m)/2, (y+n)/2)

此时鼠标会自动移动到这个窗体上


参考链接:
https://blog.csdn.net/qq_25408423/article/details/80884114
https://blog.csdn.net/seele52/article/details/17504925

到此这篇关于python中spy++的使用超详细教程的文章就介绍到这了!

Python 相关文章推荐
列举Python中吸引人的一些特性
Apr 09 Python
Python的字典和列表的使用中一些需要注意的地方
Apr 24 Python
在Python操作时间和日期之asctime()方法的使用
May 22 Python
web.py 十分钟创建简易博客实现代码
Apr 22 Python
浅谈Python2获取中文文件名的编码问题
Jan 09 Python
tensorflow TFRecords文件的生成和读取的方法
Feb 06 Python
Python中numpy模块常见用法demo实例小结
Mar 16 Python
python和mysql交互操作实例详解【基于pymysql库】
Jun 04 Python
Python实现打包成库供别的模块调用
Jul 13 Python
Python 数据的累加与统计的示例代码
Aug 03 Python
Python eval函数介绍及用法
Nov 09 Python
selenium自动化测试入门实战
Dec 21 Python
Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)
Jan 29 #Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
Jan 29 #Python
如何用python开发Zeroc Ice应用
Jan 29 #Python
详解Pymongo常用查询方法总结
Jan 29 #Python
Python3使用tesserocr识别字母数字验证码的实现
Jan 29 #Python
Python爬取梨视频的示例
Jan 29 #Python
使用Python封装excel操作指南
Jan 29 #Python
You might like
星际争霸兵种名称对照表
2020/03/04 星际争霸
php实现编辑和保存文件的方法
2015/07/20 PHP
Yii隐藏URL中index.php的方法
2016/07/12 PHP
thinkPHP多域名情况下使用memcache方式共享session数据的实现方法
2016/07/21 PHP
PHP基于MySQLI函数封装的数据库连接工具类【定义与用法】
2017/08/11 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/01/13 Javascript
jquery keypress,keyup,onpropertychange键盘事件
2010/06/25 Javascript
JS正则表达式验证数字代码
2014/01/28 Javascript
RequireJS入门一之实现第一个例子
2015/09/30 Javascript
Bootstrap按钮功能之查询按钮和重置按钮
2016/10/26 Javascript
jquery插入兄弟节点的操作方法
2016/12/07 Javascript
利用Jquery实现几款漂亮实用的时间轴(附示例代码)
2017/02/15 Javascript
解决bootstrap中使用modal加载kindeditor时弹出层文本框不能输入的问题
2017/06/05 Javascript
vue基于element-ui的三级CheckBox复选框功能的实现代码
2018/10/15 Javascript
video.js 一个页面同时播放多个视频的实例代码
2018/11/27 Javascript
详解Vue一个案例引发「内容分发slot」的最全总结
2018/12/02 Javascript
JS左右无缝轮播功能完整实例
2019/05/16 Javascript
JS实现分页导航效果
2020/02/19 Javascript
es6中使用map简化复杂条件判断操作实例详解
2020/02/19 Javascript
pycharm 使用心得(一)安装和首次使用
2014/06/05 Python
Python+django实现简单的文件上传
2016/08/17 Python
Python实现两款计算器功能示例
2017/12/19 Python
在python中只选取列表中某一纵列的方法
2018/11/28 Python
pandas ix &iloc &loc的区别
2019/01/10 Python
python 使用pandas计算累积求和的方法
2019/02/08 Python
Python3.5装饰器典型案例分析
2019/04/30 Python
使用python脚本自动创建pip.ini配置文件代码实例
2019/09/20 Python
大家都说好用的Python命令行库click的使用
2019/11/07 Python
pytorch逐元素比较tensor大小实例
2020/01/03 Python
基于MUI框架使用HTML5实现的二维码扫描功能
2018/03/01 HTML / CSS
京东全球售:直邮香港,澳门,台湾,美国,澳大利亚等地区
2017/09/24 全球购物
幼儿园中秋节活动反思
2014/02/16 职场文书
优秀应届毕业生自荐书
2014/06/29 职场文书
2014年销售经理工作总结
2014/12/01 职场文书
幼儿园教师师德承诺书
2015/04/28 职场文书
如何在Python中创建二叉树
2021/03/30 Python