有個朋友最近問我有沒有推薦 GUI 桌面應(yīng)用自動化的技術(shù),我只能回答他:
不好意思,這個真有,他是pyautogui。
主要有三大特征:
◆ 純純的 Python, 源碼一覽無余;
◆ 跨平臺,linux, windows, mac 他都能上;
◆ 操作簡單,會代碼就能上手。
一、WeB自動化文件上傳,不要太簡單
熟悉web自動化測試的大佬應(yīng)該都懂,當(dāng)采用js調(diào)用原生控件進行文件上傳的時候,最常用的是使用 pywin32 等系統(tǒng)交互庫。
當(dāng)看到pywin32那丑陋的api封裝只能爆粗口。
就為了輸入一個文件地址,需要整這么多莫名其妙的代碼(看不懂沒關(guān)系,只需要看代碼行數(shù)就夠了):
我們來看看使用 pyautogui 多么簡單:
#輸入文件名 pyautogui.write(r'd:demo.txt') # 回車 pyautogui.press('enter', presses=2)
二、跨平臺的使用和安裝
上面的代碼在mac ,linux和windows上是通用的,只是在mac和linux下需要安裝額外的依賴。
windows安裝不需要其他依賴,直接使用了python自帶的ctypes模塊:
pip install pyautogui
mac安裝需要PyObjC模塊:
pip3 install pyobjc-core pip3 install pyobjc pip3 install pyautogui
linux需要依賴python3-Xlib或者python-xlib(python2):
pip3 install python3-xlib pip3 install pyautogui
linux如果沒有安裝相關(guān)python庫可能會報錯。
Debian系發(fā)行版(其他發(fā)行版自行了解)你可能需要輸入:
sudo apt-get install scrot sudo apt-get install python3-tk sudo apt-get install python3-dev
三、基于坐標(biāo)和圖像的設(shè)計哲學(xué)
pyautogui并不需要去解析各平臺的控件結(jié)構(gòu),他的元素定位都是基于坐標(biāo)的。
所以不論你是通過手工截圖測量,還是通過自動化工具獲取,只要你能拿到坐標(biāo),你就能進行元素操作。
鼠標(biāo)操作
1、獲取坐標(biāo)
import pyautogui as ui # 獲取屏幕大小 size = ui.size() # 獲取現(xiàn)在鼠標(biāo)位置 p = ui.position() # 坐標(biāo)是否超出屏幕范圍 if_on = ui.onScreen(*p)
2、鼠標(biāo)移動
ui.moveTo(x/2, y/2, duration=2, tween=easeInCirc)
參數(shù)說明:
◆ x, y 坐標(biāo)
◆ duration 持續(xù)秒數(shù),默認是瞬間完成
◆ tween 特效,一般沒什么用
3、鼠標(biāo)拖拽, 移動到指定的坐標(biāo)
ui.dragTo(500, 500)
4、百發(fā)百中的射箭游戲
import random import time import pyautogui as ui x, y = ui.position() target = (800, 800) for i in range(10): rand_x = random.randint(0, x) rand_y = random.randint(0, y) # 隨機生成位置 print(rand_x, rand_y) ui.moveTo(rand_x, rand_y) # 移動到目標(biāo)位置 ui.dragTo(target, duration=0.2) time.sleep(1)
效果:
5、相對移動
ui.move(-500, duration=1) ui.move(yOffset=-400, duration=1) ui.move(500, duration=1) ui.move(yOffset=400, duration=1)
相對移動的小游戲:
start = 20 add_point = 10 duration = 0.5 for i in range(10): if i % 2 == 0: ui.drag(start, duration=duration) ui.drag(yOffset=start, duration=duration) else: ui.drag(-start, duration=duration) ui.drag(yOffset=-start, duration=duration) start += add_point
效果:
6、點擊
ui.click(x=None, y=None, clicks=1, # 點擊次數(shù) interval=0.0, # 間隔時間 button='right', # 右鍵 duration=0.0) # 持續(xù)時間
通過click進一步封裝了leftClick,rightClick,middleClick,doubleClicktripleClick
7、scroll
窗口滾動,但是封裝的滾動感覺比較雞肋,他是以鼠標(biāo)點擊次數(shù)為單位的,所以不知道會滾動到什么位置。
pyautogui.scroll(10) # 向上滾動 10 個 clicks >>> pyautogui.scroll(-10) # # 向下滾動 10 個 clicks >>> pyautogui.scroll(10, x=100, y=100) # 移動到位置再滾動
使用drag和dragTo會更加方便一點,還是以坐標(biāo)為依據(jù),通過操作鼠標(biāo)中鍵來實現(xiàn)窗口滾動。
比如這個例子是scroll和drag的對比:
x, y = ui.size() ui.scroll(-100) time.sleep(1) ui.scroll(100) time.sleep(1) ui.dragTo(y=y, button='middle') # 滾動到窗口底部
效果:
鍵盤操作
1、輸入框輸入
# 輸入yuz, 每個字母時間間隔 0.2 s pyautogui.write("yuz",interval=0.2)
注意:pyautogui 并不支持輸入框自動聚焦,所有輸入之前先要點擊輸入框位置。
2、按下鍵盤 press
press('enter', presses=1, interval=0.0)
相當(dāng)于鼠標(biāo)操作的 click, 可以輸入鍵盤上的按鍵, 比如 shift 鍵,enter 鍵。
所有的按鍵可以查看源碼當(dāng)中的 KEYBOARD_KEYS 或者 KEY_NAMES。
參數(shù):
◆ presses, 操作按鍵次數(shù)
◆ interval, 每次按鍵的間隔時間
所有按鍵列表:
3、熱鍵 hotkey
ui.hotkey('ctrl', 'shift', 'esc')
4、keyUp, keyDown
這是press的分解動作,相當(dāng)于鼠標(biāo)的mouseUp和mouseDown。
上面熱鍵的操作方式可以分解成:
ui.keyDown('ctrl') # 按下 ctrl ui.keyDown('shift') # 按下 shift ui.keyDown('esc') # 按下 esc ui.keyUp('esc') # 釋放 ctrl ui.keyUp('shift') # 釋放 shift ui.keyUp('ctrl') # 釋放 esc
圖像識別
坐標(biāo)定位這種方式為通用性打下了基礎(chǔ),讓pyautogui可以輕松做到跨平臺。
但是實際操作過程中很難清除的知道某個要操作的控件的確切位置,因為每次打開相同的頁面都有可能是變動的。
pyautogui 給出的解決方案非常簡單粗暴,使用圖像識別,返回在屏幕中的坐標(biāo)位置,在通過坐標(biāo)進行處理。
1、locateCenterOnScreen
返回被識別圖像的中心坐標(biāo)。
參數(shù)說明:
◆ 必傳參數(shù),圖片路徑;
◆ confidence, 識別精度,需要安裝 opencv 才能使用;
◆ grayscale, 灰度級別,能夠提升識別速度
locateCenterOnScreen('img/seven.png', confidence=0.7, grayscale=True)
現(xiàn)階段圖像識別的結(jié)果并不理想,基于圖像識別的使用還存在以下問題:
◆ 識別不到指定元素;
◆ 識別精度不夠;
◆ 查找速度比較慢
◆ 需要用到重型的opencv庫, 或許可以嘗試換用其他庫。
◆ 需要提前準(zhǔn)備被識別的圖片,如果操作元素多,手動處理素材會懷疑人生。
所以uiautogui適合的場景是跨平臺的少量原生控件交互,如果要對原生應(yīng)用控件大量操作,還是換用其他工具比較合適。
基于圖像識別的具體例子:
import time import pyautogui as ui time.sleep(3) seven = ui.locateCenterOnScreen('img/seven.png', confidence=0.7, grayscale=True) mult = ui.locateCenterOnScreen('img/multipy.png', confidence=0.7, grayscale=True) two = ui.locateCenterOnScreen('img/two.png', confidence=0.7, grayscale=True) equal = ui.locateCenterOnScreen('img/equal.png', confidence=0.7, grayscale=True) ui.click(*seven) ui.click(*mult) ui.click(*two) ui.click(*equal)
效果:
4、后期可以期待的
pyautogui現(xiàn)階段最欠缺的是無法獲取窗口。
但是可以通過PyGetWindow等工具進行集成。
你可以通過官網(wǎng)roadmap和常見問答查看今后的發(fā)展路徑。
本文由檸檬班雨澤老師原創(chuàng),轉(zhuǎn)載需注明出處!