添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

PyAutoGUI是一个纯Python的GUI自动化工具,其目的是可以用程序自动控制鼠标和键盘操作,多平台支持(Windows,OS X,Linux)。可以用 pip 安装,Github上有 源代码

下面的代码让鼠标移到屏幕中央。

import pyautogui
screenWidth, screenHeight = pyautogui.size()
pyautogui.moveTo(screenWidth / 2, screenHeight / 2)
import pyautogui
screenWidth, screenHeight = pyautogui.size()
currentMouseX, currentMouseY = pyautogui.position()
pyautogui.moveTo(100, 150)
pyautogui.click()
#  鼠标向下移动10像素
pyautogui.moveRel(None, 10)
pyautogui.doubleClick()
#  用缓动/渐变函数让鼠标2秒后移动到(500,500)位置
#  use tweening/easing function to move mouse over 2 seconds.
pyautogui.moveTo(1800, 500, duration=2, tween=pyautogui.easeInOutQuad)
#  在每次输入之间暂停0.25秒
pyautogui.typewrite('Hello world!', interval=0.25)
pyautogui.press('esc')
pyautogui.keyDown('shift')
pyautogui.press(['left', 'left', 'left', 'left', 'left', 'left'])
pyautogui.keyUp('shift')
pyautogui.hotkey('ctrl', 'c')
    pyautogui.dragRel(distance, 0, duration=0.5) # 向右
    distance -= 5
    pyautogui.dragRel(0, distance, duration=0.5) # 向下
    pyautogui.draIn gRel(-distance, 0, duration=0.5) # 向左
    distance -= 5
    pyautogui.dragRel(0, -distance, duration=0.5) # 向上

就像《魔法师的学徒》(Sorcerer’s Apprentice)会担水的扫帚,可以担水,却无力阻止水漫浴室。你的程序也可能会失控(即使是按照你的意思执行的),那时就需要中断。如果鼠标还在自动操作,就很难在程序窗口关闭它。

为了能够及时中断,PyAutoGUI提供了一个保护措施。当pyautogui.FAILSAFE = True时,如果把鼠标光标在屏幕左上角,PyAutoGUI函数就会产生pyautogui.FailSafeException异常。如果失控了,需要中断PyAutoGUI函数,就把鼠标光标在屏幕左上角。要禁用这个特性,就把FAILSAFE设置成False

PyAutoGUI支持Python 2.x和Python 3.x

  • Windows:PyAutoGUI没有任何依赖,因为它用Python的ctypes模块所以不需要pywin32
    pip3 install pyautogui复制代码
  • OS X:PyAutoGUI需要PyObjC运行AppKit和Quartz模块。这个模块在PyPI上的按住顺序是pyobjc-corepyobjc
    sudo pip3 install pyobjc-core
    sudo pip3 install pyobjc
    sudo pip3 install pyautogui复制代码
  • Linux:PyAutoGUI需要python-xlib(Python 2)、python3-Xlib(Python 3)
    sudo pip3 install python3-xlib
    sudo apt-get scrot
    sudo apt-get install python-tk
    sudo apt-get install python3-dev
    sudo pip3 install pyautogui复制代码
    num_seconds = 1.2
    #  用num_seconds秒的时间把光标移动到(x, y)位置
    pyautogui.moveTo(x, y, duration=num_seconds)
    #  用num_seconds秒的时间把光标的X轴(水平)坐标移动xOffset,
    #  Y轴(竖直)坐标向下移动yOffset。
    xOffset, yOffset = 50, 100
    pyautogui.moveRel(xOffset, yOffset, duration=num_seconds)
    
    pyautogui.click(x=moveToX, y=moveToY, clicks=num_of_clicks, interval=secs_between_clicks, button='left')
    
    pyautogui.rightClick(x=moveToX, y=moveToY)
    pyautogui.middleClick(x=moveToX, y=moveToY)
    pyautogui.doubleClick(x=moveToX, y=moveToY)
    pyautogui.tripleClick(x=moveToX, y=moveToY)
    
    pyautogui.mouseDown(x=moveToX, y=moveToY, button='left')
    pyautogui.mouseUp(x=moveToX, y=moveToY, button='left')
    
    #  每次键入的时间间隔
    secs_between_keys = 0.1
    pyautogui.typewrite('Hello world!\n', interval=secs_between_keys)
    
    pyautogui.typewrite(['a', 'b', 'c', 'left', 'backspace', 'enter', 'f1'], interval=secs_between_keys)
    
    pyautogui.hotkey('ctrl', 'a') # 全选
    pyautogui.hotkey('ctrl', 'c') # 复制
    pyautogui.hotkey('ctrl', 'v') # 粘贴
    
    pyautogui.alert('这个消息弹窗是文字+OK按钮')
    pyautogui.confirm('这个消息弹窗是文字+OK+Cancel按钮')
    pyautogui.prompt('这个消息弹窗是让用户输入字符串,单击OK')
    

    屏幕位置使用X和Y轴的笛卡尔坐标系。原点(0,0)在左上角,分别向右、向下增大。

    如果屏幕像素是$1920 \times 1080$,那么右下角的坐标是(1919, 1079)

    分辨率大小可以通过size()函数返回整数元组。光标的位置用position()返回。例如:

    while True: x, y = pyautogui.position() positionStr = 'X: {} Y: {}'.format(*[str(x).rjust(4) for x in [x, y]]) print(positionStr, end='') print('\b' * len(positionStr), end='', flush=True) except KeyboardInterrupt: print('\n') while True: x, y = pyautogui.position() positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4) print positionStr, print '\b' * (len(positionStr) + 2), sys.stdout.flush() except KeyboardInterrupt: print '\n'
    pyautogui.moveTo(100, 200)     # 光标移动到(100, 200)位置
    pyautogui.moveTo(None, 500)   # 光标移动到(100, 500)位置
    pyautogui.moveTo(600, None)   # 光标移动到(600, 500)位置
    
    pyautogui.moveTo(100, 200) #把光标移动到(100, 200)位置
    pyautogui.moveRel(0, 50)   #向下移动50
    pyautogui.moveRel(30, 0, 2)   #向右移动30
    pyautogui.moveRel(30, None)   #向右移动30
    
    #  按住鼠标左键,把鼠标拖拽到(100, 200)位置
    pyautogui.dragTo(100, 200, button='left')
    #  按住鼠标左键,用2秒钟把鼠标拖拽到(300, 400)位置
    pyautogui.dragTo(300, 400, 2, button='left')
    #  按住鼠标右键,用2秒钟把鼠标拖拽到(30,0)位置
    pyautogui.dragTo(30, 0, 2, button='right')
    

    缓动/渐变函数的作用是让光标的移动更炫。如果你不需要用到的话,你可以忽略这些。

    缓动/渐变函数可以改变光标移动过程的速度和方向。通常鼠标是匀速直线运动,这就是线性缓动/渐变函数。PyAutoGUI有30种缓动/渐变函数,可以通过pyautogui.ease*?查看。其中,pyautogui.easeInQuad()函数可以用于moveTo()moveRel()dragTo()dragRel()函数,光标移动呈现先慢后快的效果,整个过程的时间还是和原来一样。而pyautogui.easeOutQuad函数的效果相反:光标开始移动很快,然后慢慢减速。pyautogui.easeOutElastic是弹簧效果,首先越过终点,然后再反弹回来。例如:

    pyautogui.moveTo(100, 100, 2, pyautogui.easeInQuad) # 开始很快,不断减速 pyautogui.moveTo(100, 100, 2, pyautogui.easeOutQuad) # 开始和结束都快,中间比较慢 pyautogui.moveTo(100, 100, 2, pyautogui.easeInOutQuad) # 一步一徘徊前进 pyautogui.moveTo(100, 100, 2, pyautogui.easeInBounce) # 徘徊幅度更大,甚至超过起点和终点 pyautogui.moveTo(100, 100, 2, pyautogui.easeInElastic) pyautogui.click(clicks=2) # 两次单击之间停留0.25秒 pyautogui.click(clicks=2, interval=0.25) # 三击右键 pyautogui.click(button='right', clicks=2, interval=0.25) pyautogui.mouseDown(); pyautogui.mouseUp() # 按下鼠标右键 pyautogui.mouseDown(button='right') # 移动到(100, 200)位置,然后松开鼠标右键 pyautogui.mouseUp(button='right', x=100, y=200) pyautogui.typewrite('Hello world!') # 每次输入间隔0.25秒,输入Hello world! pyautogui.typewrite('Hello world!', interval=0.25)
    ['\t', '\n', '\r', ' ', '!', '"', '#', '复制代码
    , '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '__JJ_LT_JJ__', '=", "__JJ_GT_JJ__', '?', '@', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 'accept', 'add', 'alt', 'altleft', 'altright', 'apps', 'backspace', 'browserback', 'browserfavorites', 'browserforward', 'browserhome', 'browserrefresh', 'browsersearch', 'browserstop', 'capslock', 'clear', 'convert', 'ctrl', 'ctrlleft', 'ctrlright', 'decimal', 'del', 'delete', 'divide', 'down', 'end', 'enter', 'esc', 'escape', 'execute', 'f1', 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f2', 'f20', 'f21', 'f22', 'f23', 'f24', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'final', 'fn', 'hanguel', 'hangul', 'hanja', 'help', 'home', 'insert', 'junja', 'kana', 'kanji', 'launchapp1', 'launchapp2', 'launchmail', 'launchmediaselect', 'left', 'modechange', 'multiply', 'nexttrack', 'nonconvert', 'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'num9', 'numlock', 'pagedown', 'pageup', 'pause', 'pgdn', 'pgup', 'playpause', 'prevtrack', 'print', 'printscreen', 'prntscrn', 'prtsc', 'prtscr', 'return', 'right', 'scrolllock', 'select', 'separator', 'shift', 'shiftleft', 'shiftright', 'sleep', 'stop', 'subtract', 'tab', 'up', 'volumedown', 'volumemute', 'volumeup', 'win', 'winleft', 'winright', 'yen', 'command', 'option', 'optionleft', 'optionright'] __JJ_LT_JJ__/',__JJ_GT_JJ__
    #  OK和Cancel按钮的消息弹窗
    pyautogui.confirm(text='', title='', buttons=['OK', 'Cancel'])
    #  10个按键0-9的消息弹窗
    pyautogui.confirm(text='', title='', buttons=range(10))
    
    import pyautogui
    im1 = pyautogui.screenshot()
    im2 = pyautogui.screenshot('my_screenshot.png')
    

    可以定位截图在屏幕上的坐标位置。比如,你需要在计算器里输入:

    如果你不知道按钮的位置,就不能用moveTo()定位和click()点击。而且每次计算器的位置可能会变化,这时即使有来坐标也不好用了。但是如果你有要点击按钮的截图,比如数字7

    你可以调用pyautogui.locateOnScreen('calc7key.png')函数来获得7的屏幕坐标。返回的是一个元组(top, left, width, height)。这个元组可以用pyautogui.center()函数来获取截图屏幕的中心坐标。如果截图没找到,pyautogui.locateOnScreen()函数返回None

    import pyautogui
    button7location = pyautogui.locateOnScreen('pyautogui/calc7key.png')
    button7location
    
    import pyautogui
    x, y = pyautogui.locateCenterOnScreen('pyautogui/calc7key.png')
    pyautogui.click(x, y)
    

    在$1920 \times 1080$的屏幕上,定位函数需要1~2秒时间。对视频游戏(LOL、DOTA)来说就太慢了,但是上班干活还是绰绰有余。

    还是几个定位函数。都是从左上角原点开始向右向下搜索截图位置:

  • locateOnScreen(image, grayscale=False):返回找到的第一个截图Image对象在屏幕上的坐标(left, top, width, height),如果没找到返回None
  • locateCenterOnScreen(image, grayscale=False):返回找到的第一个截图Image对象在屏幕上的中心坐标(x, y),如果没找到返回None
  • locateAllOnScreen(image, grayscale=False):返回找到的所有相同截图Image对象在屏幕上的坐标(left, top, width, height)的生成器
  • locate(needleImage, haystackImage, grayscale=False):返回找到的第一个截图Image对象在haystackImage里面的坐标(left, top, width, height),如果没找到返回None
  • locateAll(needleImage, haystackImage, grayscale=False):返回找到的所有相同截图Image对象在haystackImage里面的坐标(left, top, width, height)的生成器
  • 两个locateAll*函数都可以用for循环和list()输出:

    import pyautogui
    button7location = pyautogui.locateOnScreen('pyautogui/calc7key.png', grayscale=True)
    button7location
          
    私信
  •