1. 程式人生 > >python 捕捉和模擬滑鼠鍵盤操作

python 捕捉和模擬滑鼠鍵盤操作

最近老師佈置了一個作業,要求我們建立一個6位數字的gmail賬號,然而我臉太黑,試了好多次都不成功,於是決定用python來寫一個指令碼遍歷輸入所有6位數。這就要求掌握使用python捕捉和模擬鍵盤操作了,於是我查閱了網上諸多資料,終於實現了這個功能,特此記錄下來方便以後複習。

使用的python版本為:3.6.1,使用anaconda配置的python環境
參考博文

首先安裝pyautogui庫:

conda install -c jim-hart pyautogui

pyautogui庫函式的基本介紹

PyAutoGUI使用x,y座標,螢幕左上角座標是(0, 0)

影象操作

獲取螢幕解析度

import pyautogui as pag
screenWidth, screenHeight = pag.size()

截圖功能

#  返回一個Pillow/PIL的Image物件
img=pag.screenshot()
img.save('foo.png')
pag.screenshot('foo.png')

獲得某個座標的畫素

(r,g,b)=img.getpixel((50, 200))
# (30, 132, 153)

# 判斷螢幕座標的畫素是不是等於某個值
ifEqual=pag.pixelMatchesColor(50, 200, (30, 132
, 153)) #True

如果你不需要擷取整個螢幕,還有一個可選的region引數。你可以把擷取區域的左上角XY座標值和寬度、高度傳入擷取

img = pag.screenshot(region=(0, 0, 300 ,400))

在螢幕上找到按鈕所在的座標。其實很簡單,首先對你要點選的按鈕截個圖,就叫button.png吧。然後使用locateOnScreen函式找到按鈕所在的位置

pag.locateOnScreen('button.png')
# (643, 745, 70, 29)

locateOnScreen其實就是簡單的顏色對比,如果有一個畫素不匹配,它就會返回None。這個函式返回了匹配圖形的座標,找到中間點:

x, y = pag.center((643, 745, 70, 29))  # 獲得中心點
pyautogui.click(x, y)
  • locateAllOnScreen():找到所有匹配的位置座標。

要檢查XY座標是否在螢幕上,需要用onScreen()函式來檢驗,如果在螢幕上返回True:

pag.onScreen(0, 0) #True
pag.onScreen(0, -1) #False

滑鼠操作

獲取當前滑鼠的座標

currentMouseX, currentMouseY = pag.position()

滑鼠點選

pag.click()

使用click()函式傳送虛擬滑鼠點選,預設情況下在滑鼠所在的位置點選左鍵。函式原型:

pag.click(x=cur_x, y=cur_y, button='left')

x,y是要點選的位置,預設是滑鼠當前位置
button是要點選的按鍵,有三個可選值:‘left’, ‘middle’, ‘right’

每個按鍵按下和鬆開兩個事件可以分開處理:

pag.mouseDown(x=moveToX, y=moveToY, button='left')
pag.mouseUp(x=moveToX, y=moveToY, button='left')

雙擊

pag.doubleClick()

右擊

pag.rightClick()

中擊

pag.middleClick()

滑鼠移動

pag.moveTo(x,y,duration) #  絕對座標
pag.moveRel(x,y,duration) # 相對座標

滑鼠拖拽
注意:duration時間不能太短,拖動太快有些系統會吃不消

pag.dragTo(x,y,duration)
pag.dragRel(x,y,duration)

多次點選
可以設定clicks引數,還有interval引數可以設定每次單擊之間的時間間隔。例如:

#  雙擊左鍵
pyautogui.click(clicks=2)
#  兩次單擊之間停留0.25秒
pyautogui.click(clicks=2, interval=0.25)
#  三擊右鍵
pyautogui.click(button='right', clicks=2, interval=0.25)

滾輪
使用函式scroll(),它只接受一個整數。如果值為正往上滾,值為負往下滾。

pag.scroll(200)

緩動/漸變(Tween / Easing)函式
緩動/漸變函式的作用是讓游標的移動更炫。如果你不需要用到的話,你可以忽略這些
緩動/漸變函式可以改變游標移動過程的速度和方向。通常滑鼠是勻速直線運動,這就是線性緩動/漸變函式。PyAutoGUI有30種緩動/漸變函式,可以通過pyautogui.ease*?檢視。其中,pyautogui.easeInQuad()函式可以用於moveTo(),moveRel(),dragTo()和dragRel()函式,游標移動呈現先慢後快的效果,整個過程的時間還是和原來一樣。而pyautogui.easeOutQuad函式的效果相反:游標開始移動很快,然後慢慢減速。pyautogui.easeOutElastic是彈簧效果,首先越過終點,然後再反彈回來。例如:

#  開始很慢,不斷加速
pyautogui.moveTo(100, 100, 2, pyautogui.easeInQuad)
#  開始很快,不斷減速
pyautogui.moveTo(100, 100, 2, pyautogui.easeOutQuad)
#  開始和結束都快,中間比較慢
pyautogui.moveTo(100, 100, 2, pyautogui.easeInOutQuad)
#  一步一徘徊前進
pyautogui.moveTo(100, 100, 2, pyautogui.easeInBounce)
#  徘徊幅度更大,甚至超過起點和終點
pyautogui.moveTo(100, 100, 2, pyautogui.easeInElastic)

鍵盤操作

輸入字串

pag.typewrite('Hello world')

上面的字串是一次輸入,為了唬人可以延遲輸入

pag.typewrite('Hello world!', 0.25)

PyAutoGUI鍵盤表:

字串 代表按鍵
‘enter’(或‘return’ 或 ‘\n’) 回車
‘esc’ ESC鍵
‘shiftleft’, ‘shiftright’ 左右SHIFT鍵
‘altleft’, ‘altright’ 左右ALT鍵
‘ctrlleft’, ‘ctrlright’ 左右CTRL鍵
‘tab’ (‘\t’) TAB鍵
‘backspace’, ‘delete’ BACKSPACE 、DELETE鍵
‘pageup’, ‘pagedown’ PAGE UP 和 PAGE DOWN鍵
‘home’, ‘end’ HOME 和 END鍵
‘up’, ‘down’, ‘left’,‘right’ 箭頭鍵
‘f1’, ‘f2’, ‘f3’…. F1…….F12鍵
‘volumemute’, ‘volumedown’,‘volumeup’ 有些鍵盤沒有
‘pause’ PAUSE鍵
‘capslock’, ‘numlock’,‘scrolllock’ CAPS LOCK, NUM LOCK, 和 SCROLLLOCK 鍵
‘insert’ INS或INSERT鍵
‘printscreen’ PRTSC 或 PRINT SCREEN鍵
‘winleft’, ‘winright’ Win鍵
‘command’ Mac OS X command鍵
  • keyDown():按下某個鍵
  • keyUp():鬆開某個鍵
  • press():一次完整的擊鍵,前面兩個函式的組合。
  • hotkey(‘ctrl’,’c’):熱鍵函式

訊息彈窗函式

pyautogui.alert('這個訊息彈窗是文字+OK按鈕')
pyautogui.confirm('這個訊息彈窗是文字+OK+Cancel按鈕')
pyautogui.prompt('這個訊息彈窗是讓使用者輸入字串,單擊OK')
#返回使用者輸入的字串,如果使用者什麼都不輸入,則返回None

保護措施(Fail-Safes)

Python移動滑鼠、點選鍵盤非常快,有可以導致其他應用出現問題。在這種情況下,程式可能會失控(即使是按照你的意思執行的),那時就需要中斷。如果滑鼠還在自動操作,就很難在程式視窗關閉它。

為了能夠及時中斷,PyAutoGUI提供了一個保護措施。當pyautogui.FAILSAFE = True時,如果把滑鼠游標在螢幕左上角,PyAutoGUI函式就會產生pyautogui.FailSafeException異常。如果失控了,需要中斷PyAutoGUI函式,就把滑鼠游標在螢幕左上角。要禁用這個特性,就把FAILSAFE設定成False

pag.FAILSAFE = False

通過把pyautogui.PAUSE設定成float或int時間(秒),可以為所有的PyAutoGUI函式增加延遲。預設延遲時間是0.1秒。在函式迴圈執行的時候,這樣做可以讓PyAutoGUI執行的慢一點,非常有用。例如:

pag.PAUSE = 2.5
pag.moveTo(100,100);
pag.click()

尋找6位數gmail郵箱

經過一晚上的奮戰,終於找到了一個6位數的gmail郵箱名,成功把作業提交了,指令碼程式碼如下

# -*- coding: utf-8 -*-
"""
Created on Sat Sep 23 00:23:10 2017

@author: WangTong
"""

import pyautogui as pag
import time

pag.FAILSAFE = True
output=open('C:\\Users\\WangTong\\Desktop\\尋找gmail\\output.txt','w+')
pag.moveTo(100,800)
pag.scroll(100)
pag.moveTo(500,1720)#右移
pag.dragTo(1000,1720,0.5)
try:
    for num in range(800000,1000000):
        flag=True
        pag.moveTo(1057,754)#移動到選擇使用者名稱視窗
        pag.click()
        pag.hotkey('ctrl','a')
        pag.press('delete')
        pag.typewrite(str(num))
        pag.moveTo(800,754)#移動到選擇使用者名稱視窗
        pag.click()
        time.sleep(1)
        img = pag.screenshot(region=(540, 440, 10,1))
        for i in range(1,10):
            (r,g,b)=img.getpixel((i,0))
            if g<100:
                flag=False# 出現了紅框,說明該使用者名稱已經有人用了
                break
        if flag:
            #之前可能是網速較慢,延時5s再判斷一次
            flag=True
            pag.click()
            time.sleep(5)
            img = pag.screenshot(region=(540, 440, 10,1))
            for i in range(1,10):
                (r,g,b)=img.getpixel((i,0))
                if g<100:
                    flag=False
                    break
            if flag:
                #這個密碼可以使用,但也存在google掛掉的情況,無論如何,先註冊試試
                pag.moveTo(1057,870)#設定密碼
                pag.click()
                pag.hotkey('ctrl','a')
                pag.press('delete')
                pag.typewrite('dasdhasiduha')
                pag.moveTo(1057,990)#確認密碼
                pag.click()
                pag.hotkey('ctrl','a')
                pag.press('delete')
                pag.typewrite('dasdhasiduha')
                pag.moveTo(1450,1680)#下一步
                pag.click()
                pag.moveTo(920,1520)#按鍵
                pag.click()
                pag.moveTo(1250,1580)#我同意
                pag.click()
                time.sleep(4)
                img = pag.screenshot(region=(160, 450, 1 ,1))
                (r,g,b)=img.getpixel((0, 0))
                #可以(74, 140, 246)
                #不可以(255, 255, 255)
                if r<150:#註冊失敗
                    print(num,'可以')
                    pag.moveTo(40,100)#返回上一層
                    pag.click()
                    time.sleep(1)
                    pag.scroll(100)
                    pag.moveTo(500,1720)#右移
                    pag.dragTo(1000,1720,0.5)
                    output.write(str(num)+':Ok')
                    output.write('\n')
                else:#註冊成功
                    print(num,'不可以')
                    pag.scroll(100)
                    pag.moveTo(500,1720)#右移
                    pag.dragTo(1000,1720,0.5)
                    output.write(str(num)+':No')
except:
    print('error')
finally:
    output.close()

總體思路就是遍歷所有6位數使用者名稱,如果該使用者名稱已經被人註冊了,使用者名稱輸入框會變成紅色提示,如果沒有被人註冊,就是灰色輸入框,所以我就依靠輸入框的畫素值來判斷該使用者名稱是否可以使用。不過有時候會因為網速問題加上gmail註冊介面的一些莫名其妙的問題,一個賬號明明已經被人註冊了,但是輸入進去之後不會有任何提示,必須要點選下一步才能提示你已經被人註冊了,所以我就把完整的註冊流程給模擬了一邊,並且找了註冊成功和註冊失敗介面中的某一個不一樣的畫素點作為區分,如果註冊失敗了,介面不會跳轉,只要繼續迴圈過程即可,如果註冊成功了,為了保險起見,我將這個可以註冊的賬號輸出的output.txt檔案裡,然後返回上一個介面繼續嘗試下一個數字。不過要注意的一點就是,無論註冊成功還是失敗,介面的位置都會變化,這個時候一定要將介面調整到右上角,不然之前設定的畫素點座標就錯了。最後我跑了一箇中午,找到了兩個可以使用的數字,第一個不知道因為什麼原因已經被人註冊了但是誤判為沒有被註冊,但是第二個數字可以使用,於是我的作業就完成了。

Ps:好多同學隨手一試就找到了一個可以使用的使用者名稱,我用指令碼試了兩千多個數字才找到一個,這就是歐皇和非酋的區別了吧/(ㄒoㄒ)/~~