 然后打開spy++,查看該程序的窗口信息。
然后打開spy++,查看該程序的窗口信息。 可以看到,這個程序主窗口的句柄為 00090816(十六進制數(shù)),值得注意的是,這個句柄是每次打開程序時,windows隨機生成的。故不能直接指定句柄號來操作窗口。在python中可以使用win32*模塊來調(diào)用windows函數(shù),之前你得安裝pywin32。使用win32gui.FindWindow和win32gui.FindWindowEx函數(shù)來拿到句柄。具體用法為:FindWindow(lpClassName=None, lpWindowName=None):描述:自頂層窗口(也就是桌面)開始搜索條件匹配的窗體,并返回這個窗體的句柄。不搜索子窗口、不區(qū)分大小寫。找不到就返回0參數(shù):lpClassName:字符型,是窗體的類名,這個可以在Spy++里找到。lpWindowName:字符型,是窗口名,也就是標(biāo)題欄上你能看見的那個標(biāo)題。說明:這個函數(shù)我們僅能用來找主窗口。FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None);描述:搜索類名和窗體名匹配的窗體,并返回這個窗體的句柄。不區(qū)分大小寫,找不到就返回0。參數(shù):hwndParent:若不為0,則搜索句柄為hwndParent窗體的子窗體。hwndChildAfter:若不為0,則按照z-index的順序從hwndChildAfter向后開始搜索子窗體,否則從第一個子窗體開始搜索。lpClassName:字符型,是窗體的類名,這個可以在Spy++里找到。lpWindowName:字符型,是窗口名,也就是標(biāo)題欄上你能看見的那個標(biāo)題。說明:找到了主窗口以后就靠它來定位子窗體啦。來源: http://blog.csdn.net/seele52/article/details/17504925
可以看到,這個程序主窗口的句柄為 00090816(十六進制數(shù)),值得注意的是,這個句柄是每次打開程序時,windows隨機生成的。故不能直接指定句柄號來操作窗口。在python中可以使用win32*模塊來調(diào)用windows函數(shù),之前你得安裝pywin32。使用win32gui.FindWindow和win32gui.FindWindowEx函數(shù)來拿到句柄。具體用法為:FindWindow(lpClassName=None, lpWindowName=None):描述:自頂層窗口(也就是桌面)開始搜索條件匹配的窗體,并返回這個窗體的句柄。不搜索子窗口、不區(qū)分大小寫。找不到就返回0參數(shù):lpClassName:字符型,是窗體的類名,這個可以在Spy++里找到。lpWindowName:字符型,是窗口名,也就是標(biāo)題欄上你能看見的那個標(biāo)題。說明:這個函數(shù)我們僅能用來找主窗口。FindWindowEx(hwndParent=0, hwndChildAfter=0, lpszClass=None, lpszWindow=None);描述:搜索類名和窗體名匹配的窗體,并返回這個窗體的句柄。不區(qū)分大小寫,找不到就返回0。參數(shù):hwndParent:若不為0,則搜索句柄為hwndParent窗體的子窗體。hwndChildAfter:若不為0,則按照z-index的順序從hwndChildAfter向后開始搜索子窗體,否則從第一個子窗體開始搜索。lpClassName:字符型,是窗體的類名,這個可以在Spy++里找到。lpWindowName:字符型,是窗口名,也就是標(biāo)題欄上你能看見的那個標(biāo)題。說明:找到了主窗口以后就靠它來定位子窗體啦。來源: http://blog.csdn.net/seele52/article/details/17504925對于一個窗口下的多個子窗口,可以通過類名和窗口名進行區(qū)分,若有多個子窗口的類名和窗口名相同,則只能從第一個開始迭代查找。當(dāng)然,如果我們知道子窗口的排列順序,可以對FindWindowEx函數(shù)進行簡單的封裝,通過索引號查找指定窗口的句柄。
| 1234567891011 | deffind_idxSubHandle(pHandle, winClass, winName =None, index=0):     """    已知子窗口的窗體類名,窗口名    尋找第index號個同類型的兄弟窗口    """    asserttype(index) ==intandindex >=0    handle =win32gui.FindWindowEx(pHandle, 0, winClass, winName)     whileindex > 0:         handle =win32gui.FindWindowEx(pHandle, handle, winClass, winName)         index -=1    returnhandle | 
若要獲取任意子窗口的句柄,則可以建立一個索引數(shù)組,然后多次調(diào)用find_idxSubHandle 函數(shù),寫成一個遞歸函數(shù)的形式:
| 123456789101112 | deffind_subHandle(pHandle, winClassList):     """    遞歸尋找子窗口的句柄    pHandle是祖父窗口的句柄
 
     asserttype(winClassList) ==list    iflen(winClassList) ==1:         returnfind_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])         returnfind_subHandle(pHandle, winClassList[1:]) | 
好了,只要能拿到句柄,一切就都好辦了。
按照上一篇中的步驟,一步一步模擬操作就可以了。
1)在下載地址對應(yīng)的文本編輯框中輸入要下載的網(wǎng)址。如下圖所示:

在spy++中可以看出,主程序中一共有2個編輯框,除了下載地址的編輯框,還有就是右下角的那個。并且可以注意到,編輯框的窗口名就是編輯框中的文本,因此在程序運行過程中,改變編輯框的文本,其窗口名就會發(fā)生變化。故只通過類名加索引的方式獲取這個編輯框的句柄。
| 1 | edithd=find_subHandle(MHandle,[('Edit',None,1)]) # 下載地址輸入框 | 
模擬向輸入框中輸入網(wǎng)址,可以使用win32gui.SendMessage函數(shù)給輸入框發(fā)送消息。
| 1 | win32gui.SendMessage(edithd,win32con.WM_SETTEXT,None,url) # 輸入下載地址 | 
2)點擊 添加任務(wù) 按鈕。
| 12 | btAddhd =find_subHandle(MHandle,[('Button',"",2),('Button',u"添加任務(wù)",0)])win32gui.SendMessage(btAddhd,win32con.BM_CLICK,None,None) | 
這時列表中就會出現(xiàn) 已加入的任務(wù)。

3)點擊 整理任務(wù) 按鈕。
| 12 | sorthd=find_subHandle(MHandle,[('Button',u"整理任務(wù)",0)]) #win32gui.SendMessage(sorthd,win32con.BM_CLICK,None,None) | 
這時列表中會顯示網(wǎng)盤地址和文件ID

待全部解析完后, 整理任務(wù) 按鈕旁邊出現(xiàn) 解析勾選 按鈕。
4)點擊 解析勾選 按鈕
| 12 | parsehd=find_subHandle(MHandle,[('Button',u"解析勾選",0)]) #win32gui.PostMessage(parsehd,win32con.BM_CLICK,None,None) | 
注意,這里使用PostMessage來處理消息。主要是由于點擊 解析勾選 按鈕后,會彈出對話框,如果使用SendMessage,主程序就會阻塞,直至對話框關(guān)閉。而主程序又必須在發(fā)送完消息后捕獲對話框句柄,然后將其關(guān)閉。這就導(dǎo)致了一個死循環(huán),除非人工將對話框關(guān)閉。關(guān)于PostMessage和SendMessage的區(qū)別,如下:
PostMessage(hWnd, Msg, wParam, lParam)描述:在消息隊列中加入為指定的窗體加入一條消息,并馬上返回,不等待線程對消息的處理。參數(shù):hWnd:整型,接收消息的窗體句柄Msg:整型,要發(fā)送的消息,這些消息都是windows預(yù)先定義好的,可以參見系統(tǒng)定義消息(System-Defined Messages))wParam:整型,消息的wParam參數(shù)lParam:整型,消息的lParam參數(shù)說明:簡單說,就是給指定程序發(fā)一個消息,這些消息都用整型編好號,作為windows的常量可以查詢的。在這里,我們用的就是win32con這個庫里定義的WM_COMMAND這個消息,具體的wParam和lParam是根據(jù)消息的不同而不同的。具體請根據(jù)MSDN查閱。
查閱MSDN的消息時,會發(fā)現(xiàn)有的wParam定義了low word和high word,這是什么呢?wParam的定義是32位整型,high word就是他的31至16位,low word是它的15至0位,如圖。當(dāng)參數(shù)超過兩個,wParam和lParam不夠用時,可以將wParam就給拆成兩個int16來使用。這種時候在Python里記得用把HIWORD的常數(shù)向左移16位,再加LOWORD,即wParam = HIWORD<<16+LOWORD。
來源: http://blog.csdn.net/seele52/article/details/17542265SendMessage(hWnd, Msg, wParam, lParam)
描述:在消息隊列中加入為指定的窗體加入一條消息,直到窗體處理完信息才返回。參數(shù):hWnd:整型,接收消息的窗體句柄Msg:整型,要發(fā)送的消息,這些消息都是windows預(yù)先定義好的,可以參見系統(tǒng)定義消息(System-Defined Messages).aspx#system_defined)wParam:整型,消息的wParam參數(shù)lParam:整型,消息的lParam參數(shù)說明:wParam和iparam根據(jù)具體的消息不同而有不同的定義,詳情參閱Part 2.來源: http://blog.csdn.net/seele52/article/details/176186155)關(guān)閉煩人的對話框
上步說過,當(dāng)點擊勾選解析 按鈕時,就會彈出下面的對話框。我們需要點擊 取消 按鈕,或者直接點右下角的關(guān)閉 按鈕。
由于后面還會出現(xiàn)對話框,對于這類只需點擊關(guān)閉按鈕的操作,我們可以寫個函數(shù)封裝。
def closeDialog(win_name):handle = get_wHandle(u'#32770',win_name) # Dialog的類名為 #32770PRint(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)然后調(diào)用這個函數(shù), closeDialog(u"是否啟用VIP模式解析")6)選中 全選。 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)7)點擊 復(fù)制鏈接 按鈕。 copyhd = find_subHandle(MHandle,[('Button',u"復(fù)制鏈接",0)])win32gui.PostMessage(copyhd,win32con.BM_CLICK,None,None)此時,又會彈出煩人的對話框。利用前面寫的函數(shù),關(guān)閉對話框。closeDialog(u"復(fù)制成功")8)從系統(tǒng)剪切板中讀取鏈接地址。完成后關(guān)閉程序。 win32clipboard.OpenClipboard()
text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT)win32clipboard.CloseClipboard()win32gui.SendMessage(MHandle,16)注意:1、這些步驟需按順序執(zhí)行,前一個步驟的結(jié)果直接影響下一步的進行。2、由于每一步執(zhí)行需要時間,而每步所需的時間不可預(yù)測,故需要一個狀態(tài)量指示當(dāng)前狀態(tài)。在這個程序中,我們發(fā)現(xiàn)控件 Afx:400000:b:10003:900015:0 的名字每步執(zhí)行完后都會響應(yīng)變化,故可根據(jù)名字來控制程序流的執(zhí)行。--》1--》2--》
--》3--》
--》4--》5--》
--》6--》7--》
--》8通過查詢控件名,等待每步執(zhí)行完成。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"請整理任務(wù) →")waitState(MHandle,u"← 請點此解析")waitState(MHandle,u"復(fù)制真實鏈接 →")waitState(MHandle,u"引導(dǎo)完畢..")3. 全部的程序和代碼見我的資源(http://download.csdn.net/detail/shawpan/9755395)
新聞熱點
疑難解答