zoukankan      html  css  js  c++  java
  • 使用 pyautogui 进行跨平台的 GUI 自动化操作

    有个朋友最近问我有没有推荐 GUI 桌面应用自动化的技术,我只能回答他:不好意思,这个真有,他是 pyautogui。主要有三大特征:

    • 纯纯的 python, 源码一览无余;
    • 跨平台,linux, windows, mac 他都能上;
    • 操作简单,会代码就能上手。

    pyautogui 进行 web 自动化文件上传不要太简单。熟悉 web 自动化测试的大佬应该都懂,当采用 js 调用原生控件进行文件上传的时候,最常用的是使用 pywin32 等系统交互库。

    当看到 pywin32 那丑陋的 api 封装只能爆粗口。就为了输入一个文件地址,需要整这么多莫名其妙的代码(看不懂没关系,只需要看代码行数就够了):

    我们来看看使用 pyautogui 多么简单:

    #输入文件名
    pyautogui.write(r'd:demo.txt')
    # 回车
    pyautogui.press('enter', presses=2)

    pyautogui 不支持中文输入。但是可以复制剪切板,间接实现中文输入:

    import pyperclip

    pyperclip.copy('D:用户.html')
    time.sleep(2)
    pyautogui.hotkey('ctrl''v')
    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 如果没有安装相关 python 库可能会报错。 Debian 系发行版(其他发行版自行了解)你可能需要输入:

    sudo apt-get install scrot
    sudo apt-get install python3-tk
    sudo apt-get install python3-dev
    

    鼠标操作

    pyautogui 并不需要去解析各平台的控件结构,他的元素定位都是基于坐标的。所以不论你是通过手工截图测量,还是通过自动化工具获取,只要你能拿到坐标,你就能进行元素操作。

    获取坐标

    import pyautogui as ui
    # 获取屏幕大小
    size = ui.size()
    # 获取现在鼠标位置
    p = ui.position()
    # 坐标是否超出屏幕范围
    if_on = ui.onScreen(*p)

    鼠标移动

    ui.moveTo(x/2, y/2, duration=2, tween=easeInCirc)
    

    参数说明:

    • x, y 坐标
    • duration 持续秒数,默认是瞬间完成
    • tween 特效,一般没什么用。

    鼠标拖拽, 移动到指定的坐标

    ui.dragTo(500, 500)
    

    百发百中的射箭游戏

    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)
        # 移动到目标位置
        ui.dragTo(target, duration=0.2)
        time.sleep(1)
    

    效果:

    相对移动

    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

    效果:

    点击操作

    ui.click(x=None,
             y=None,
             clicks=1,  # 点击次数
             interval=0.0,  # 间隔时间
             button='right',  # 右键
             duration=0.0)  # 持续时间

    通过 click 进一步封装了 leftClick, rightClick, middleClick, doubleClick, tripleClick

    scroll 窗口滚动操作

    窗口滚动,但是封装的滚动感觉比较鸡肋,他是以鼠标点击次数为单位的,所以不知道会滚动到什么位置。

    pyautogui.scroll(10)   # 向上滚动 10 个 clicks
    >>> pyautogui.scroll(-10)  # # 向下滚动 10 个 clicks
    >>> pyautogui.scroll(10, x=100, y=100# 移动到位置再滚动

    使用 drag 和 dragTo 会更加方便一点,还是以坐标为依据,通过操作鼠标中键来实现窗口滚动,比如这个例子是 scroll 和 drag 的对比:

    x, y = ui.size()
    ui.scroll(-100)
    time.sleep(1)
    ui.scroll(100)
    time.sleep(1)
    ui.dragTo(y=y, button='middle'# 滚动到窗口底部

    效果:

    键盘操作

    输入框输入

    # 输入yuz, 每个字母时间间隔 0.2 s
    pyautogui.write("yuz",interval=0.2)

    注意:pyautogui 并不支持输入框自动聚焦,所有输入之前先要点击输入框位置。

    按下键盘 press

    press('enter', presses=1, interval=0.0)
    

    相当于鼠标操作的 click, 可以输入键盘上的按键, 比如 shift 键,enter 键。所有的按键可以查看源码当中的 KEYBOARD_KEYS 或者 KEY_NAMES。

    参数:

    • presses, 操作按键次数
    • interval, 每次按键的间隔时间

    所有按键列表:

    热键 hotkey

    ui.hotkey('ctrl', 'shift', 'esc')
    

    keyUp, keyDown

    这是 press 的分解动作,相当于鼠标的 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
    

    图像识别

    坐标定位这种方式为通用性打下了基础,让 pyautogui 可以轻松做到跨平台。但是实际操作过程中很难清除的知道某个要操作的控件的确切位置,因为每次打开相同的页面都有可能是变动的。pyautogui 给出的解决方案非常简单粗暴,使用图像识别,返回在屏幕中的坐标位置,在通过坐标进行处理。

    locateCenterOnScreen

    返回被识别图像的中心坐标。参数说明:

    • 必传参数,图片路径;
    • confidence, 识别精度,需要安装 opencv 才能使用;
    • grayscale, 灰度级别,能够提升识别速度。
    locateCenterOnScreen('img/seven.png', confidence=0.7, grayscale=True)

    现阶段图像识别的结果并不理想,基于图像识别的使用还存在以下问题:

    • 识别不到指定元素;

    • 识别精度不够;

    • 查找速度比较慢

    • 需要用到重型的 opencv 库, 或许可以尝试换用其他库。

    • 需要提前准备被识别的图片,如果操作元素多,手动处理素材会怀疑人生。

      所以 uiautogui 适合的场景是跨平台的少量原生控件交互,如果要对原生应用控件大量操作,还是换用其他工具比较合适。

      基于图像识别的具体例子:

    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)

    效果:

    后期可以期待的

    pyautogui 现阶段最欠缺的是无法获取窗口。但是可以通过 PyGetWindow 等工具进行集成。你可以通过官网 roadmap 和 常见问答 查看今后的发展路径。

  • 相关阅读:
    linux常用命令整理
    pg_sql常用查询语句整理
    python 爬取媒体文件(使用chrome代理,启动客户端,有防火墙)
    python 爬取媒体文件(无防火墙)
    python读写符号的含义
    python数据分析开发中的常用整理
    wget: 无法解析主机地址
    ## nginx 使用
    iptables防火墙
    【redis】Could not connect to Redis at 127.0.0.1:6379: Connection refused
  • 原文地址:https://www.cnblogs.com/wagyuze/p/12887144.html
Copyright © 2011-2022 走看看