英雄联盟Python Bot键盘失效:pyautogui无法触发技能升级操作
问题
使用Python3结合pyautogui开发《英雄联盟》Bot时,通过pywin32实现的鼠标左右点击功能正常,但pyautogui的按键功能仅在文本框中有效,无法触发技能等操作,其中level_up函数完全无法工作。相关代码如下:
from pyautogui import * import pyautogui import time import keyboard import numpy as np import random import win32api, win32con def click_right(x,y):#works fine win32api.SetCursorPos((x,y)) win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN,0,0) time.sleep(.01) win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP,0,0) def click_left(x,y):#works fine win32api.SetCursorPos((x,y)) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0) time.sleep(.1) win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0) def type(word): for char in word: pyautogui.keyDown(char) time.sleep(.05) pyautogui.keyUp(char) def buy_item(item):#item is a string, works fine click_left(1209,998)#open shop time.sleep(.2) click_left(313,281)#click to search for item time.sleep(.2) type(item)#type item name time.sleep(.1) click_right(318,354)#buy item time.sleep(.1) click_left(1170,217)#close shop def buy_items(items):#items is a list of strings, works fine click_left(1209, 998) # open shop time.sleep(.2) for item in items: click_left(313, 281) # search item time.sleep(.2) type(item) time.sleep(.1) click_right(318, 354) time.sleep(.1) click_left(1170, 217) #doesn't work def level_up(ability):#ability is a char in 'qwer' with pyautogui.hold('ctrl'): pyautogui.press(['q']) def main(): time.sleep(3) buy_items(['dagger', 'zeal', 'cloth']) time.sleep(1) level_up('q') # if __name__ == '__main__': main()
解决方案
问题根源
《英雄联盟》这类基于DirectX的游戏会直接读取底层硬件输入,而pyautogui是通过模拟系统GUI事件发送按键,这种上层模拟的输入会被游戏的输入拦截机制忽略,因此仅在文本框这类系统控件中有效。
基于现有pywin32的修复方案
利用win32api的keybd_event函数直接发送底层键盘事件,游戏可以识别到。修改level_up函数如下:
# 补充按键常量映射 KEY_MAP = { 'q': win32con.VK_Q, 'w': win32con.VK_W, 'e': win32con.VK_E, 'r': win32con.VK_R, 'ctrl': win32con.VK_CONTROL } def press_single_key(key_code): win32api.keybd_event(key_code, 0, 0, 0) time.sleep(0.03) win32api.keybd_event(key_code, 0, win32con.KEYEVENTF_KEYUP, 0) def level_up(ability): # 按住Ctrl键 win32api.keybd_event(KEY_MAP['ctrl'], 0, 0, 0) time.sleep(0.02) # 按下对应技能键 press_single_key(KEY_MAP[ability]) time.sleep(0.02) # 松开Ctrl键 win32api.keybd_event(KEY_MAP['ctrl'], 0, win32con.KEYEVENTF_KEYUP, 0)
更合适的替代库
- pynput:封装更友好,底层实现贴近硬件级模拟,对游戏兼容性更好。示例代码:
from pynput.keyboard import Key, Controller import time keyboard = Controller() def level_up(ability): with keyboard.pressed(Key.ctrl): keyboard.press(ability.lower()) keyboard.release(ability.lower()) time.sleep(0.05)
- SendInput(win32api):微软推荐的新一代输入模拟API,比
keybd_event更稳定,兼容性更强,不过代码相对繁琐。
额外注意事项
- 游戏需设置为窗口化或无边框窗口模式,全屏模式可能屏蔽外部模拟输入。
- 运行脚本时需获取管理员权限,否则无法向游戏进程发送底层输入。
- 控制输入频率,加入适量
time.sleep,避免触发游戏反作弊机制。
内容的提问来源于stack exchange,提问作者Phillip Feldman
相关产品推荐
相关产品推荐

