手把手教你使用pyautogui


最近公司项目需要,要在三百多台终端上测一个windows软件的兼容性,所以想做个UI自动化,于是看到了pyautogui这个包,从名字就能看出,他是做gui界面相关的包,
pyautogui最方便的地方就是,你不需要去用代码定位元素,你只需要用截图就行,例如你要识别桌面上某个应用,你只需要截图这个应用,然后通过这个截图和当前桌面对比即可找到图标的位置,说到这里,大家应该就会想到,那我是不是把代码封装好之后,后面不管产品怎么迭代,我只要更换截图就可以了?是的!这就是我在这里写篇博客的目的,我看了一下,基本没有一个完整的源码教程,所以我想给大家分享一个完完整整的教程,因为他是真的好用,代码简单,后期维护成本低。
首先是基本用法,这个百度一下一大堆,这里是pypi的文档,自行阅读:https://pypi.org/project/PyAutoGUI/
简单的贴两行官方文档中代码:

import pyautogui
pyautogui.moveTo(100, 150) # Move the mouse to the x, y coordinates 100, 150.
pyautogui.click()

上面就是一个把鼠标移到(100,150)这个坐标的代码,并且左键鼠标单击,当然有鼠标单击就有双击,各种操作查看上面文档即可,那我们如何定位我们想要的内容在哪呢?请继续往下看:

假设我们想要定位“计算机”的坐标然后去点击他,可以通过如下代码:

#这是你的目标图标,也就是你的截图,下面找他的时候会用到
appname = ROOT_DIR + '/testimage/' + target + '.png'
##根据桌面路径进行截屏
##获取当前桌面路径
threshold = 0.85
path = os.path.join(os.path.expanduser('~'), "Desktop")
hwnd = win32gui.FindWindow(None, path)
app = QApplication(sys.argv)
screen = QApplication.primaryScreen()
img = screen.grabWindow(hwnd).toImage()
# img = ImageGrab.grab()

##保存截屏
root_desk = ROOT_DIR + '/desktop.png'
img.save(root_desk)
##等待图片保存
time.sleep(0.5)
# 支持图片名为中英文名,也支持路径中英文
imsrc = cv2.imdecode(np.fromfile(root_desk, dtype=np.uint8), -1)
imobj = cv2.imdecode(np.fromfile(appname, dtype=np.uint8), -1)

# 匹配图标位置
pos = ac.find_template(imsrc, imobj, threshold)

pos就是当前匹配到的路径
这是基本用法,其他方法可以在我后面的源码中查看

下面说坑:
1.python和第三方包版本
之前使用的是python2,于是去安装对应的py包,结果一顿骚造作之后,发现总是有问题,鼠标老是移动不到目标坐标位置,于是换了py3.6版本和对应的依赖包,搞定
2.windows用户权限弹框

你没看错,就是这个玩意,能匹配到,但是不能点击,最后直接把这个弹框在windows系统上禁用了,如果你有好的办法,可以联系我,一起共享
3.突然操作失效,例如定位坐标出错,点击不了鼠标
这个解决办法有点呵呵,重启电脑,然后再运行代码,嗯,没问题了,wtf

说完坑,然后说如何做到前面说的只需要维护截图就能更新迭代。

1、定义好你的操作和对应的函数。
在py文件里面添加如下代码:

ACTIONCN2EN = {"匹配": "match", "输入内容": "input_type", "复制入内容": "input_copy", "左键单击": "click_once",
               "左键双击": "click_twice", "Enter键单击": "click_enter_once", "等待出现": "wait", "全选": "select_all",
               '点击按键': 'type_write', '检测结果': 'check_result', '鼠标滚动': 'scroll'}
@time_sleep
def click_once():
    pyautogui.click()

上面我就举一个鼠标左键点击一次的例子,节约篇幅
然后定义动作,这里新建一个txt文件:
里面输入如下:

定义好之后,可以用python打开这个txt文件,然后通过eval(ACTIONCN2EN[act])(params)去执行函数即可
如果想要其他的步骤,直接在后面添加即可,例如我以->作为分隔符,定义了如下测试流程:

通过如下代码即可解析步骤:

with open(file, encoding='utf-8') as f:
action_str = f.read()

# 保证'动作.txt'里,动作最后的换行符无影响
action_str = action_str.strip('\n')
# 保证动作之间的单个换行符跟->等效。若有多个换行符,放到if act=''里
action_str = action_str.replace('\n', '->')
# print(action_str)
action_list = action_str.split('->')
for act in action_list:
if act == '':  # 当同时有多个换行符时,act就是空,在这里排除
    pass
else:
    try:  # 防止同一Dj99ZzZz个action里,有一个动作异常就不执行其他动作
        act.encode('utf-8')
        ##提取action具体动作的括号里的内容,如match(QQ-单发输入框)
        p1 = re.compile(r'[(](.*?)[)]', re.S)
        params = re.findall(p1, act)  # 查找后返回list,都放在[0]里,()内无东西,即无参数,返回空列表
        act = act.split('(')[0]

        if params == []:
            print(u"调用方法为:{}".format(act))
            eval(ACTIONCN2EN[act])()
        else:
            params = params[0]
            if params == 'arg1':
                try:
                    params = sys.argv[1]
                except IndexError as ex:
                    raise Exception('请传第1个参数')
            if params == 'arg2':
                try:
                    params = sys.argv[2]
                except IndexError as ex:
                    raise Exception('请传第2个参数')
            print(u"调用方法为:{}({})".format(act, params))
            eval(ACTIONCN2EN[act])(params)  # 参数可以有多个,参数之间用,分隔。目前只支持一个参数
    except Exception as e:
        print(e)
        break

然后根据动作,截图好每个图标就可以,下次产品迭代或者新增功能,直接更新action.txt文件的步骤和截图就行了
github代码地址:https://github.com/ruhaoyu/uitest


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM