appium通过图像识别技术opencv解决密码键盘的模拟输入密码问题

  • Post author:
  • Post category:其他


appium自动化测试框架,具体信息不便我重复,网上能够查找的资料也很多

我项目中在做自动化测试的过程中,遇到密码键盘,需要进行模拟点击输入的问题,使用appium提供的sent_keys方法不管用,原因是密码键盘必须得点击密码键盘进行输入才能够通过。

密码键盘的原理是每次点击一个按键,进行一次加密,点击结束后,按登录才能够登录通过。而send_keys的输入方法是直接使用系统的键盘发送键值到输入框,没有经过点击操作。

密码键盘的一个难点就在于,它没有id,而appium提供的定位方法大都是通过ID,name,class等元素进行页面定位的,看过所有的定位方法后,发现了通过坐标值也可以进行定位,而密码键盘要想定位成功,必须通过图像识别,识别出键盘所在的位置坐标信息

下面的功能就是通过图像识别方法对密码键盘所在的坐标进行识别。

所遇到的密码键盘如下图所示


面还有输入框的内容,我进行了截取。


解决思路:

1、图像识别,然后点击坐标

2、开发配合,给特定的app包,解除安全键盘。

而对于非自己的app是无法使用第二种方法的。

图像识别找到了opencv里面有match Template方法,可以在图片中找指定的图片,


步骤:


1、首先需要操作的位置进行截图并保存起来,切记按原图大小截取,尽可能小,比如:


2、然后就是在截取的屏幕上面查找这些数字对应的位置

3、按照位置在屏幕上点击


实现代码:

以需要输入密码为例,我写了如下代码,需要传入截图图片路径,还需要输入的密码。前面我已经将各个数字的图片保存在了本地,并以n0.jpg,n1.jpg,…保存,并和脚本放在一起。

我使用python写的脚本,当然你还需要安装opencv,下载路径:http://opencv.org/releases.html下载后吧build下面的python里面的cv2.pyd文件目录下面的lib\site-packages里面

代码如下

#coding:utf-8
import os
import time

import cv2
import numpy as np
import matplotlib.pyplot as plt

def get_pay_keyboard_number_location(im, pwd):
    numbers = set(list(pwd))
    templates = {}
    positions = {}
    nimgpath = ""   #数字图片不在同目录时使用
    for i in numbers:
        templates[i]  = os.path.join(nimgpath, "n{}.jpg".format(i))

    start = time.time()
    img_rgb = cv2.imread(im)

    for teNum, tepath in templates.items():
        # print(tepath)
        template = cv2.imread(tepath)
        h, w = template.shape[:-1]

        res = cv2.matchTemplate(img_rgb, template, cv2.TM_CCOEFF_NORMED)
        threshold = .95    # 匹配度参数,1为完全匹配
        loc = np.where(res >= threshold)
        if len(loc) > 0:
            positions[teNum] = zip(*loc[::-1])[0]
        else:
            print("Can not found number: [{}] in image: [{}].".format(tepath, im))

    end = time.time()
    print(end-start)

    return [positions[n] for n in pwd]

if __name__ == "__main__":
    ls = get_pay_keyboard_number_location('keyboard.jpg', '1234567890')
    print(ls)

上面的代码实现了获取每个数字的坐标,并以列表进行返回。

拿到坐标后就可以直接的通过appium的tap,如

TouchAction(driver).long_press(x = 180,y = 1400).perform()

进行点击操作了。

代码不一定严谨,欢迎指正



版权声明:本文为jsqfengbao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。