pyautogui库,自动化玩游戏主要知识

"""
OS X:
PyAutoGUI需要PyObjC运行AppKit和Quartz模块。这个模块在PyPI上的按住顺序是pyobjc-core和pyobjc
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

"""

import pyautogui
print(pyautogui.size()) # 获取屏幕分辨率
# Size(width=1920, height=1080)
print(pyautogui.position()) # position()
# 光标的位置用position()返回
# Point(x=1529, y=578)

# 3.3 onScreen(x, y)检查XY坐标是否在屏幕上
# 屏幕位置(x, y)传入函数onScreen(x, y)返回布尔值True和False
print(pyautogui.onScreen(1920,1080))# False

# 3.4 基本代码演示
import pyautogui # 导入库
screenWidth,screenHeight = pyautogui.size() # 获取屏幕分辨率
pyautogui.moveTo(screenWidth / 2,screenHeight / 2)# 鼠标移动到 屏幕中心
currentMouseX,currentMouseY = pyautogui.position() # 获取鼠标位置
print(currentMouseX,currentMouseY) # 打印鼠标位置 输出 屏幕中心值

# 3.5保护措施
#
# 3.5.1 PAUSE 更改默认的操作延迟时间,默认0.1秒
pyautogui.PAUSE = 2.5 # 根改操作,延迟时间为2.5s
# 3.5.2 FAILSAFE把鼠标光标在屏幕左上角(0, 0)报错终止运行
# pyautogui.FAILSAFE = True时,如果把鼠标光标在屏幕左上角,PyAutoGUI函数就会产生pyautogui.FailSafeException异常。用于终止程序运行,防止死循环。
# pyautogui.FAILSAFE = True
# 3.5.3 另外对所有Python程序死循环都有效的Alt + C热键也可以强制终止。
# print('Press Ctrl+C to quit')#


# 4. 鼠标函数
# 4.1 moveTo()鼠标移动
#
# 鼠标移动到绝对坐标
# pyautogui.moveTo(x,y)
# 坐标系的原点是左上角。X轴(水平)坐标向右增大,Y轴(竖直)坐标向下增大。。
pyautogui.moveTo(100,200) #
# 一般鼠标光标都是瞬间移动到指定的位置,如果你想让鼠标移动的慢点,可以通过参数duration控制移动时间
pyautogui.moveTo(100,200,duration=1.2)
# 鼠标移动到相对坐标
# 以鼠标当前位置为原点,X轴(横向)向右移动,Y轴(竖直)向下移动,负值反方向移动。
pyautogui.moveRel(50,100,duration=1.5)
# 4.2 click()鼠标点击
# click()函数就是让鼠标先移动,再单击,默认是左键,
pyautogui.click(x=100,y=200,duration=2)
pyautogui.click(50,100,clicks=3,interval=0.25,button='right') # 先移动到绝对位置,单击三次,间隔0.25s, 鼠标右键
# 其中,button属性可以设置成left(左键),middle(中键)和right(右键)。
# 为了操作方便,PyAutoGUI提供了rightClick(), middleClick, doubleClick(),tripleClick()和来实现右右键点击、中键点击、双击、三击的操作,可读性更好:
pyautogui.rightClick(x=100,y=200)
pyautogui.middleClick(x=100,y=200)
pyautogui.doubleClick(x=100,y=200) # 双击
pyautogui.tripleClick(x=100,y=200) # 3击

# 4.3 scroll()鼠标滚轮
# scroll函数控制鼠标滚轮的滚动。正数向上滚动,负数向下滚动,只接收一个整数。
pyautogui.scroll(-10)
# 可以先移动,再滚动。
pyautogui.scroll(10,x=100,y=100)


# 4.4 按下mouseDown()和松开mouseUp()
# 每个按键按下和松开两个事件可以分开处理:
pyautogui.mouseDown(x=100,y=200,button='left')
pyautogui.mouseUp(x=100,y=200,button='left')
pyautogui.mouseUp(button='right',x=100,y=200)

# 4.5 dragTo()拖拽
# 拖拽的意思是:按下鼠标键并拖动鼠标。PyAutoGUI 提供了两个函数:dragTo()和 dragRel()。它的参数和 moveTo()和 moveRel() 一样

pyautogui.dragTo(100,200,button='left')
pyautogui.dragTo(100,200,2,button='left')

pyautogui.dragRel(100,200,duration=2,button='left')
pyautogui.dragRel(100,200,2,button='left')

# 4.6 移动速度渐变
# 缓动/渐变函数可以改变光标移动过程的速度和方向。通常鼠标是匀速直线运动,这就是线性缓动/渐变函数。PyAutoGUI有30种缓动/渐变函数,可以通过pyautogui.ease*?查看。
#
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) # 徘徊幅度更大,甚至超过起点和终点


# 5. 键盘控制函数
# 5.1 typewrite()字符输入
# 键盘控制的主要函数就是typewrite()。这个函数可以实现字符输入。要在两次输入间增加时间间隔,可以用interval参数。typewrite()函数只能用于单个字符键,不能按SHITF和F1这些功能键。
#
pyautogui.typewrite('Hello world!') # 输入Hello world!
pyautogui.typewrite('Hello world!', interval=0.25) # 每次输入间隔0.25秒,输入Hello world!
pyautogui.typewrite('Hello world! ', interval=0.1) # 模拟按键依次键入Hello world!字符并换行( ),按键的时间间隔0.1秒。


# 多个按键连续输入可以列表的方式:
#
pyautogui.typewrite(['a', 'b', 'c', 'left', 'backspace', 'enter', 'f1'], interval=0.1) # 依然按列表中的按键,间隔0.1秒


# 5.2 press()、keyDown()、keyUp()几种按键方式
# 按下键盘按键,可以用press()函数把pyautogui.KEYBOARD_KEYS里面按键对应的字符串输入进去。
#
pyautogui.press('esc') # 按一下键盘Esc键

# 和typewrite()函数一样,可以用数组把一组键传入press()。
#
pyautogui.press(['left','left','left']) # 键盘上三次点击左方向键左箭头

# press()函数其实按下然后松开两个动作。每个按键的按下和松开也可以单独调用,实际是press() 的拆分动作,是按下按键keyDown()和释放按键keyUp()函数的包装。

pyautogui.press('a') # 按一次a

# 等价于:
#
pyautogui.keyDown('a') # 按下a不释放
pyautogui.keyUp('a') # 释放a
#

# 适合组合使用:按住shift键,连续按3下左方向键,然后再松开shift键。
#
pyautogui.keyDown('shift') # 按下shift不释放
pyautogui.press('left') # 一次左方向键左箭头
pyautogui.press('left') # 二次左方向键左箭头
pyautogui.press('left') # 三次左方向键左箭头
pyautogui.keyUp('shift') # 释放shift键


# 为了更高效的输入热键,PyAutoGUI提供了hotkey()函数,像Ctrl+A或Ctrl+Shift+1都可以用hotkey()函数来实现:

pyautogui.hotkey('ctrl','a')
pyautogui.hotkey('ctrl', 'a') # 全选

# 等价于:

pyautogui.keyDown('ctrl') # 按下Ctrl不释放
pyautogui.keyDown('a') # 按下a不释放
pyautogui.keyUp('a') # 释放a
pyautogui.keyUp('ctrl') # 释放Ctrl键


# 5.3下面就是press(),keyDown(),keyUp()和hotkey()函数可以输入的按键名称:
print(pyautogui.KEYBOARD_KEYS)

# [’ ’, ‘ ’, ‘ ’, ’ ‘, ‘!’, ‘"’, ‘#’, ‘$’, ‘%’, ‘&’, "’", ‘(’, ‘)’, ‘*’, ‘+’, ‘,’, ‘-’, ‘.’, ‘/’, ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘:’, ‘;’, ‘<’, ‘=’, ‘>’, ‘?’, ‘@’, ‘[’, ‘’, ‘]’, ‘^’, ‘_’, ‘`’, ‘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’]
# 可以这样使用:
pyautogui.KEYBOARD_KEYS[:10] # 用列表方式获取前十

#[’ ’, ‘ ’, ‘ ’, ’ ', ‘!’, ‘"’, ‘#’, ‘$’, ‘%’, ‘&’]


#6. 消息弹窗函数
# PyAutoGUI通过Tkinter实现了4种纯Python的消息弹窗函数,和JavaScript类似。
#6.1 alert()单按钮的消息弹窗

pyautogui.alert(text='',title='',button='OK') # 显示一个简单的带文字和OK按钮的弹窗,用户点击后返回button的文字

# 6.2 The confirm()多按钮的消息弹窗
#
pyautogui.confirm(text='',title='',buttons=['OK','Cancel'])
# pyautogui.confirm(text='', title='', buttons=['OK', 'Cancel']) # 显示OK和Cancel按钮的消息弹窗。用户点击后返回button的文字。
# pyautogui.confirm(text='', title='', buttons=range(10)) # 显示0-9十个按键的消息弹窗。用户点击后返回button的文字

# 6.3 The prompt()可以输入的消息弹窗
pyautogui.prompt(text='',title='',default='') # 显示一个可以输入消息的弹窗,带ok,cancel按钮,点OK返回输入的文字,Cancel返回None

# 6.4 The password() 可以输入密码的消息弹窗
pyautogui.password(text='',title='',default='',mask='*')
#
# pyautogui.password(text='', title='', default='', mask='*') # 样式同prompt(),用于输入密码,消息用*表示。带OK和Cancel按钮。用户点击OK按钮返回输入的文字,点击Cancel按钮返回None。

# Pillow 的许多功能需要外部库的支持,对应的依赖包有很多,其中不需要安装所有的依赖包如果仅仅需要其基本能运行。如果安装下面的依赖包没有安装成功,可尝试安装官方文档中更详细的依赖包
# $ sudo apt-get install python-dev python-setuptools
# $ sudo apt-get install libjpeg8 libjpeg62-dev libfreetype6 libfreetype6-dev
# $ sudo pip install pillow

# 在terminal中输入上述代码即可成功使用pillow库。


# 7. 截屏函数
# PyAutoGUI用Pillow/PIL库实现图片相关的识别和操作。PyAutoGUI可以截屏并保存为图片文件,然后定位这些截屏在屏幕上的位置。与sikuli类似,把屏幕上的按键截取下来,然后定位,就可以执行点击等操作了。
# 截屏功能需要安装Pillow模块。OS X用screencapture命令,是系统自带的。Linux用户用scrot命令,可以通过sudo apt-get install scrot安装。
# 由于Ubuntu上安装Pillow时缺少PNG和JPEG依赖,所以安装比较复杂,具体可以看Ubuntu论坛。不过用miniconda可以解决这些问题,如果Ubuntu或Mint上安装了miniconda,可以直接conda install pillow来安装。
#
# 7.1 screenshot()截屏
# 调用screenshot()将返回Image对象(有关详细信息,请参阅Pillow或PIL模块文档)。传递文件名字符串会将屏幕截图保存到文件中,并将其作为Image对象返回。

img1 = pyautogui.screenshot()
img2 = pyautogui.screenshot('my_screenshot.png')
#
# im1 = pyautogui.screenshot()
# im2 = pyautogui.screenshot('my_screenshot.png')
# 1
# 2
# 在一个1920×1080的屏幕上,screenshot()函数要消耗100微秒不快也不慢。
#
# im = pyautogui.screenshot(region=(0, 0, 300 ,400)) # 如果不需要截取整个屏幕,还有一个可选的region参数。可以控制截取区域的左上角X、Y坐标值和宽度、高度的参数,用来截取。


# 7.2 locateOnScreen()比较图片并定位
# 如果你有一个图片文件想在上面做点击操作,你可以用locateOnScreen()函数来定位。就是和图片做简单的颜色对比,适合查找屏幕不固定按钮的位置。
#
pyautogui.locateOnScreen('looks.png')
# pyautogui.locateOnScreen('looks.png') # 找到会返回(最上角坐标x,y,宽度,高度)4个数值。如果有一个像素不匹配,它就会返回None。
# 1
# 7.3 pyautogui.center()获取中心点

x,y = pyautogui.center((643,745,70,29))
# x, y = pyautogui.center((643, 745, 70, 29)) # 获得中心点x,y的坐标

# 7.4 locateCenterOnScreen()等价于上面的两步操作,直接获得图形的中心坐标:
#
# x, y = pyautogui.locateCenterOnScreen('pyautogui/calc7key.png') # 获得图形的中心坐标x,y
# pyautogui.click(x, y) # 获取坐标后可以配合鼠标点击等操作


# 定位时间需要1~2秒,对即时游戏来说就太慢了,但是大多数情况下还是很好用的。
#
# 7.5 更多用法
# 有几个“定位”功能。他们都开始查看屏幕的左上角(或图像)并向右看,然后向下看。
# locateOnScreen(image, grayscale=False)- 返回image屏幕上第一个找到的实例的(左,顶部,宽度,高度)坐标。ImageNotFoundException如果在屏幕上找不到则会引发。
# locateCenterOnScreen(image, grayscale=False)- 返回image屏幕上第一个找到的实例中心的(x,y)坐标。ImageNotFoundException如果在屏幕上找不到则会引发。
# locateAllOnScreen(image, grayscale=False) - 返回一个生成器,该生成器生成(左,顶部,宽度,高度)元组,用于在屏幕上找到图像的位置。
# locate(needleImage, haystackImage, grayscale=False)-返回(左,上,宽度,高度)的第一坐标发现的实例needleImage在haystackImage。ImageNotFoundException如果在屏幕上找不到则会引发。
# locateAll(needleImage, haystackImage, grayscale=False)- 返回一个生成器(生成(左,顶部,宽度,高度)元组的位置needleImage)haystackImage。
# “locate all”函数可用于for循环或传递给list():
#
# for pos in pyautogui.locateAllOnScreen('someButton.png')
# print(pos)
# (1101, 252, 50, 50)
# (59, 481, 50, 50)
# (1395, 640, 50, 50)
# (1838, 676, 50, 50)
#
# list(pyautogui.locateAllOnScreen('someButton.png'))

# [(1101, 252, 50, 50), (59, 481, 50, 50), (1395, 640, 50, 50), (1838, 676, 50, 50)]
#
# 这些“定位”功能费时,加速它们的最好方法是传递一个region参数(4个整数元组(左,顶部,宽度,高度))来仅搜索屏幕的较小区域而不是全屏:
#
# pyautogui.locateOnScreen('someButton.png', region=(0,0, 300, 400))
# 1
# 7.6 灰度值匹配
# 可以传递参数grayscale=True给locate函数,能提供轻微的加速(大约30%-ish)。这会使图像和屏幕截图中的颜色去色,从而加快速度,但容易导致误判失误。
#

pyautogui.locateOnScreen('cakc7key.png',grayscale=True)


# 8 像素匹配
# 8.1要获取截屏某个位置的RGB像素值,可以用Image对象的getpixel()方法:
#
im = pyautogui.screenshot()
im.getpixel((100,200)) #
# im = pyautogui.screenshot() # 先获取屏幕截图
# im.getpixel((100, 200)) # 再获取截图x,y的RGB值


# 8.2 pixel()可以将前面两步封装在一起
#
# pyautogui.pixel(100, 200)
# 1
# 8.3 pixelMatchesColor()如果你只是要检验一下指定位置的像素值,可以直接用x,y坐标和RGB颜色。返回True和False
#
# pyautogui.pixelMatchesColor(100, 200, (255, 255, 255))
# pyautogui.pixelMatchesColor(100, 200, (255, 255, 245), tolerance=10) # tolerance参数可以指定RGB颜色的误差范围


# 8.4 不稳定的情况
#
# pyautogui.pixelMatchesColor(100, 100, (60, 63, 65)) # 这样用,有时候不稳定。不规律的抛出错误
# 1
# OSError: windll.user32.ReleaseDC failed : return 0
#
# print(pyautogui.screenshot().getpixel((100, 100)) == (60, 63, 65)) # 可以改成这样使用
# 1
# 9.0 安装错误的解决办法
# 9.1 pip install pyautogui
# 提示“UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xa2”
# Using cached https://files.pythonhosted.org/packages/f1/54/740939161eb3471e8f7
# 75ce9b0fcac0e54c36bf63501e51f2cd7158f587d/PyGetWindow-0.0.3.tar.gz
# Complete output from command python setup.py egg_info:
# Traceback (most recent call last):
# File “”, line 1, in
# File “C:Users edgameAppDataLocalTemppip-install-tqy3ahwxpygetwindow
# setup.py”, line 11, in
# long_description = fh.read()
# UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xa2 in position 905: ille
# gal multibyte sequence
# 解决办法:pyautogui依赖的是pygetwindow0.04,先pip install pygetwindow0.0.1,再安装pyautogui
#
# 9.2 locateonscreen 函数无法添加confidence参数
# 提示TypeError: _locateAll_python() got an unexpected keyword argument 'confidence
# 解决办法:需要先安装opencv
# pip install opencv-python
#
# 10.0 PyAutoGUI键盘表的部分解释
# ‘ ’(TAB制表符), ‘ ’(换行符), ‘ ’,
# ’ ‘, ‘!’, ‘"’, ‘#’, ‘$’, ‘%’, ‘&’, "’", ‘(’, ‘)’, ‘*’, ‘+’, ‘,’, ‘-’, ‘.’, ‘/’, (各种符号)
# ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, (数字)
# ‘:’, ‘;’, ‘<’, ‘=’, ‘>’, ‘?’, ‘@’, ‘[’, ‘’, ‘]’, ‘^’, ‘_’, ‘`’, (各种符号)
# ‘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’, (26英文字符)
# ‘{’, ‘|’, ‘}’, ‘~’, (各种符号)
# ‘accept’, ‘add’,
# ‘alt’, ‘altleft’, ‘altright’, (Alt键,区分左、右)
# ‘apps’,
# ‘backspace’(Backspace退格键)
# ‘browserback’, ‘browserfavorites’, ‘browserforward’, ‘browserhome’, ‘browserrefresh’, ‘browsersearch’, ‘browserstop’, (浏览器后退、收藏、前进、主页、刷新、搜索、停止)
# ‘capslock’, (CapsLock大小写锁定键)
# ‘clear’, ‘convert’,
# ‘ctrl’, ‘ctrlleft’, ‘ctrlright’, (Ctrl键,区分左、右)
# ‘decimal’,
# ‘del’, ‘delete’, (Delete键删除光标右边字符)
# ‘divide’,
# ‘down’, (下键头)
# ‘end’, (End键结尾)
# ‘enter’, (Enter回车键)
# ‘esc’, ‘escape’, (Esc键退出)
# ‘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’, (F1-F23功能键)
# ‘final’,
# ‘fn’, (Fn键)
# ‘hanguel’, ‘hangul’, ‘hanja’, ‘help’,
# ‘home’, (Home键)
# ‘insert’, (Insert键)
# ‘junja’, ‘kana’, ‘kanji’, ‘launchapp1’, ‘launchapp2’, ‘launchmail’, ‘launchmediaselect’,
# ‘left’, (左箭头)
# ‘modechange’, ‘multiply’, ‘nexttrack’, ‘nonconvert’,
# ‘num0’, ‘num1’, ‘num2’, ‘num3’, ‘num4’, ‘num5’, ‘num6’, ‘num7’, ‘num8’, ‘num9’, (数字小键盘0-9键)
# ‘numlock’, (数字小键盘锁定键)
# ‘pagedown’, ‘pageup’, (PageDown键下翻一页,PageUp键上翻一页,)
# ‘pause’, (Pause暂停键)
# ‘pgdn’, ‘pgup’, ‘playpause’, ‘prevtrack’,
# ‘print’, ‘printscreen’, (Prt Scr键)
# ‘prntscrn’, ‘prtsc’, ‘prtscr’, ‘return’,
# ‘right’, (右箭头)
# ‘scrolllock’, (Scroll Lock键)
# ‘select’, ‘separator’,
# ‘shift’, ‘shiftleft’, ‘shiftright’, (Shift键,区分左、右)
# ‘sleep’, (Sleep睡眠键)
# ‘stop’, ‘subtract’, ‘tab’,
# ‘up’, (上箭头)
# ‘volumedown’, ‘volumemute’, ‘volumeup’, (音量-、静音、音量+)
# ‘win’, ‘winleft’, ‘winright’, (Win键,区分左、右)
# ‘yen’,
# ‘command’, (苹果Command键)
# ‘option’, ‘optionleft’, ‘optionright’ (苹果Option键,区分左、右)

原文地址:https://www.cnblogs.com/llx--20190411/p/15262380.html