airtest是網(wǎng)易開發(fā)的一款基于圖象識別的ui自動化框架炭分,其對元素操作的流程是先對元素進(jìn)行截圖驾孔,再和客戶端當(dāng)前界面截圖進(jìn)行對比瓶盛,找出位置,執(zhí)行點擊操作呕乎。
這樣的操作免除了傳統(tǒng)的查找控件的繁雜积担,但是對元素的斷言卻不夠精細(xì),尤其在不僅僅判斷元素是否存在猬仁,而且還要對文本的內(nèi)容進(jìn)行檢查時帝璧,可以說無能為力了。
想要解決這個問題湿刽,可以使用回歸傳統(tǒng)的元素查找方式(airtest內(nèi)置了各端通過元素查找方式的api)的烁,查找到元素,再判斷他的文本屬性诈闺,得到內(nèi)容渴庆;但這樣的方式第一需要在元素的映射方式上增加傳統(tǒng)的例如xpath的關(guān)系,第二很多時候由于不規(guī)范開發(fā)等原因,元素的定位屬性往往不容易確定襟雷,花費(fèi)時間查找其實已經(jīng)丟失了圖像識別控件的便利性刃滓。
在實際的操作中(我的項目是pc端+安卓端雙端互動的場景),我發(fā)現(xiàn)可以利用airtest本身的api耸弄,外加ocr的python庫咧虎,做到對元素內(nèi)容的識別,從而解決這個問題计呈。
大概的思路是老客,先用airtest本身的api,將待識別內(nèi)容截圖扣下來震叮,然后利用ocr的庫進(jìn)行對其內(nèi)容識別胧砰。
理論上,如果你的設(shè)備分辨率不會變更苇瓣,那么其實不需要用到airtest的api尉间,直接用固定的位置,通過opencv等圖像處理的庫進(jìn)行摳圖保存即可击罪,但由于生產(chǎn)設(shè)備的分辨率不能保證哲嘲,因此,需要一個相對的位置媳禁,對這個位置眠副,airtest里有直接可用的方法,這個方法也是其本身對分辨率兼容的辦法竣稽。
airtest通過你截圖時記錄的坐標(biāo)囱怕,設(shè)備分辨率,來生成一個recordpos毫别,這個pos其實就是一個用來計算當(dāng)分辨率不同時他的坐標(biāo)偏移量娃弓。
具體怎么通過recordpos進(jìn)行計算坐標(biāo),這里就不贅述了岛宦,主要說一下通過recordpos進(jìn)行元素查找的方法台丛,這個方法是get_predict_area,有四個參數(shù)砾肺,分別是record_pos(截取控件圖片時的偏移量)挽霉、image_wh(空間的寬高)、image_resolution(截取圖片時記錄的設(shè)備分辨率)变汪、screen_resolution(查找控件時所在設(shè)備的實際分辨率)侠坎。
該方法會返回一個四角坐標(biāo),我們把這個四角坐標(biāo)用內(nèi)置的圖片處理方法疫衩,在設(shè)備及圖上進(jìn)行截圖保存硅蹦,就可以獲取到待識別控件的圖片啦,然后再用ocr庫對這個圖片進(jìn)行識別闷煤,就可以得到控件的文本內(nèi)容了童芹。
示例代碼如下(只適用于本人的硬件設(shè)備,用作參考):
dev = device()
stu_answer_num = r'./valid_pic/stu_answer_num.png' # 答題區(qū)域的截圖路徑
interact_pic_path = r'./valid_pic/snap_interact.png' # 互動界面的截圖路徑
interact_image = dev.snapshot(interact_pic_path) # 把互動界面截圖保存
from PIL import Image
import pytesseract
from airtest import aircv
from airtest.core.cv import Predictor
screen_resolution = aircv.get_resolution(interact_image) # 獲取互動界面截圖的實際分辨率
# 動態(tài)創(chuàng)建類繼承自Predictor鲤拿,修改類參數(shù)假褪,偏移值DEVIATION為0,用以獲取精準(zhǔn)的截圖區(qū)域
predictor = type('Pos', (Predictor,), {'DEVIATION': 0})
xmin, ymin, xmax, ymax = predictor.get_predict_area(record_pos=(0.404, -0.213), image_wh=(265, 45),
image_resolution=(1919, 1040),
screen_resolution=screen_resolution) # 獲取答題區(qū)域的截圖坐標(biāo)
predict_area = aircv.crop_image(interact_image, (xmin, ymin, xmax, ymax))
aircv.imwrite(stu_answer_num, predict_area) # 將待識別區(qū)域進(jìn)行截圖保存
answer_str = pytesseract.image_to_string(Image.open(stu_answer_num), 'chi_sim') # 識別出的文字類似’全 班 共 參 與 : 1/1‘
print(answer_str)
if answer_str.find('參 與'):
answer_str = answer_str.split(' ')[-1] # 取1/1
answer_num = int(answer_str.split('/')[0]) # 取答題人數(shù)
return answer_num
return