本文共 5752 字,大约阅读时间需要 19 分钟。
上篇讲了,如何使用“ 城通网盘批量下载器 v2.0 ”来下载城通网盘的文件。其主要操作集中在主界面中,所以我们首先使用python来模拟在主界面的操作。对于一个窗口下的多个子窗口,可以通过类名和窗口名进行区分,若有多个子窗口的类名和窗口名相同,则只能从第一个开始迭代查找。当然,如果我们知道子窗口的排列顺序,可以对FindWindowEx函数进行简单的封装,通过索引号查找指定窗口的句柄。
1 2 3 4 5 6 7 8 9 10 11 | def find_idxSubHandle(pHandle, winClass, winName = None , index = 0 ): """ 已知子窗口的窗体类名,窗口名 寻找第index号个同类型的兄弟窗口 """ assert type (index) = = int and index > = 0 handle = win32gui.FindWindowEx(pHandle, 0 , winClass, winName) while index > 0 : handle = win32gui.FindWindowEx(pHandle, handle, winClass, winName) index - = 1 return handle |
若要获取任意子窗口的句柄,则可以建立一个索引数组,然后多次调用find_idxSubHandle 函数,写成一个递归函数的形式:
1 2 3 4 5 6 7 8 9 10 11 12 | def find_subHandle(pHandle, winClassList): """ 递归寻找子窗口的句柄 pHandle是祖父窗口的句柄
assert type (winClassList) = = list if len (winClassList) = = 1 : return find_idxSubHandle(pHandle, winClassList[ 0 ][ 0 ], winClassList[ 0 ][ 1 ], winClassList[ 0 ][ 2 ]) else : pHandle = find_idxSubHandle(pHandle, winClassList[ 0 ][ 0 ], winClassList[ 0 ][ 1 ], winClassList[ 0 ][ 2 ]) return find_subHandle(pHandle, winClassList[ 1 :]) |
好了,只要能拿到句柄,一切就都好办了。
按照上一篇中的步骤,一步一步模拟操作就可以了。
1)在下载地址对应的文本编辑框中输入要下载的网址。如下图所示:
在spy++中可以看出,主程序中一共有2个编辑框,除了下载地址的编辑框,还有就是右下角的那个。并且可以注意到,编辑框的窗口名就是编辑框中的文本,因此在程序运行过程中,改变编辑框的文本,其窗口名就会发生变化。故只通过类名加索引的方式获取这个编辑框的句柄。
1 | edithd = find_subHandle(MHandle,[( 'Edit' , None , 1 )]) # 下载地址输入框 |
模拟向输入框中输入网址,可以使用win32gui.SendMessage函数给输入框发送消息。
1 | win32gui.SendMessage(edithd,win32con.WM_SETTEXT, None ,url) # 输入下载地址 |
2)点击 添加任务 按钮。
1 2 | btAddhd = find_subHandle(MHandle,[( 'Button' ," ",2),('Button',u" 添加任务", 0 )]) win32gui.SendMessage(btAddhd,win32con.BM_CLICK, None , None ) |
这时列表中就会出现 已加入的任务。
3)点击 整理任务 按钮。
1 2 | sorthd = find_subHandle(MHandle,[( 'Button' ,u "整理任务" , 0 )]) # win32gui.SendMessage(sorthd,win32con.BM_CLICK, None , None ) |
这时列表中会显示网盘地址和文件ID
待全部解析完后, 整理任务 按钮旁边出现 解析勾选 按钮。
4)点击 解析勾选 按钮
1 2 | parsehd = find_subHandle(MHandle,[( 'Button' ,u "解析勾选" , 0 )]) # win32gui.PostMessage(parsehd,win32con.BM_CLICK, None , None ) |
注意,这里使用PostMessage来处理消息。主要是由于点击 解析勾选 按钮后,会弹出对话框,如果使用SendMessage,主程序就会阻塞,直至对话框关闭。而主程序又必须在发送完消息后捕获对话框句柄,然后将其关闭。这就导致了一个死循环,除非人工将对话框关闭。关于PostMessage和SendMessage的区别,如下:
查阅MSDN的消息时,会发现有的wParam定义了low word和high word,这是什么呢?wParam的定义是32位整型,high word就是他的31至16位,low word是它的15至0位,如图。当参数超过两个,wParam和lParam不够用时,可以将wParam就给拆成两个int16来使用。这种时候在里记得用把HIWORD的常数向左移16位,再加LOWORD,即wParam = HIWORD<<16+LOWORD。
来源:
SendMessage(hWnd, Msg, wParam, lParam)
5)关闭烦人的对话框
上步说过,当点击勾选解析 按钮时,就会弹出下面的对话框。我们需要点击 取消 按钮,或者直接点右下角的关闭 按钮。
由于后面还会出现对话框,对于这类只需点击关闭按钮的操作,我们可以写个函数封装。
def closeDialog(win_name): handle = get_wHandle(u'#32770',win_name) # Dialog的类名为 #32770 print(handle) time.sleep(0.5) win32gui.SendMessage(handle,win32con.WM_CLOSE,0,0)
def get_wHandle(win_class_name,win_name): while not win32gui.FindWindow(win_class_name, win_name): time.sleep(0.2) return win32gui.FindWindow(win_class_name, win_name)
closeDialog(u"是否启用VIP模式解析")
allSelhd=find_subHandle(MHandle,[('Button',"",1),('Button',u"全选",0)]) # 4F0A4E if win32gui.SendMessage(allSelhd,win32con.BM_GETCHECK): win32gui.SendMessage(allSelhd,win32con.BM_CLICK,None,None) win32gui.SendMessage(allSelhd,win32con.BM_CLICK,None,None)
copyhd = find_subHandle(MHandle,[('Button',u"复制链接",0)]) win32gui.PostMessage(copyhd,win32con.BM_CLICK,None,None)
closeDialog(u"复制成功")
win32clipboard.OpenClipboard() text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT) win32clipboard.CloseClipboard() win32gui.SendMessage(MHandle,16)
def getState(pHandle): time.sleep(1) afx = win32gui.FindWindowEx(pHandle,None,'Afx:400000:b:10003:900015:0',None) return win32gui.GetWindowText(afx) def waitState(pHandle,msg): while msg != getState(pHandle): time.sleep(0.2)
waitState(MHandle,u"请整理任务 →")
waitState(MHandle,u"← 请点此解析")
waitState(MHandle,u"复制真实链接 →")
waitState(MHandle,u"引导完毕..")
转载地址:http://jrhci.baihongyu.com/