如何编写仅作用于指定游戏窗口、支持最小化运行的Python脚本
Python实现后台游戏Bot方案
你要的「操作仅作用于指定游戏窗口、运行时不影响正常使用电脑、窗口最小化仍可运行、具备完整PC权限」的需求,核心是放弃前台键鼠模拟方案,改用Windows窗口消息机制实现后台交互,全程不需要抢占键鼠焦点。
前置准备
先安装依赖库,在PyCharm的终端执行:pip install pywin32 pillow numpy
注意:如果目标游戏搭载内核级反作弊(如EAC、BattlEye、腾讯TP内核模式),以下方案会被拦截,且有极高封号风险,不建议尝试。
第一步:锁定目标游戏窗口
所有后台操作都需要先拿到游戏窗口的唯一句柄(hwnd),不要靠固定窗口标题硬匹配,通过枚举窗口+关键词筛选的方式找最稳:
import win32gui import win32con import win32api import time import random from PIL import Image import win32ui import numpy as np GAME_TITLE_KEYWORD = "替换为你游戏窗口标题的关键词,比如原神、DNF" game_hwnd = None def get_game_hwnd(hwnd, _): global game_hwnd if win32gui.IsWindowVisible(hwnd) and GAME_TITLE_KEYWORD in win32gui.GetWindowText(hwnd): game_hwnd = hwnd win32gui.EnumWindows(get_game_hwnd, None) if not game_hwnd: raise RuntimeError("未检测到运行中的目标游戏,请先启动游戏再运行脚本")
第二步:实现无干扰后台操作
不要用pyautogui、pynput这类全局键鼠模拟库——这类库是向系统发送全局输入事件,会抢占你正在使用的键鼠,窗口最小化时操作会直接打到桌面上,完全不符合需求。
直接通过PostMessage向游戏窗口句柄定向发送键鼠消息,消息会直接进入游戏的消息队列,不管窗口在前台、被遮挡还是最小化,都不会影响你正常使用电脑:
def backend_click(rel_x: int, rel_y: int): """ 后台鼠标左键点击 :param rel_x: 相对于游戏窗口客户区左上角的X坐标,左上角为(0,0) :param rel_y: 相对于游戏窗口客户区左上角的Y坐标 """ coor_param = win32api.MAKELONG(rel_x, rel_y) win32api.PostMessage(game_hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, coor_param) # 加入随机延迟模拟真人操作,避免固定间隔被反作弊检测 time.sleep(random.uniform(0.06, 0.18)) win32api.PostMessage(game_hwnd, win32con.WM_LBUTTONUP, 0, coor_param) def backend_key_press(vk_code: int): """ 后台键盘按键 :param vk_code: 按键对应的Windows虚拟键码,比如W键为0x57、数字1键为0x31 """ win32api.PostMessage(game_hwnd, win32con.WM_KEYDOWN, vk_code, 0) time.sleep(random.uniform(0.04, 0.12)) win32api.PostMessage(game_hwnd, win32con.WM_KEYUP, vk_code, 0)
第三步:适配最小化运行场景
用上面的消息投递方案本身已经支持最小化窗口操作,要解决两个常见坑:
- 不要用全屏截图、前台找图的方式识别游戏画面,最小化状态下前台API截不到窗口内容,改用
PrintWindow接口实现后台截图,不需要把窗口切到前台:
def backend_screenshot() -> Image.Image: """后台截取游戏窗口画面,支持窗口被遮挡、移出屏幕状态""" left, top, right, bottom = win32gui.GetClientRect(game_hwnd) w, h = right - left, bottom - top hdc = win32gui.GetWindowDC(game_hwnd) dc_obj = win32ui.CreateDCFromHandle(hdc) mem_dc = dc_obj.CreateCompatibleDC() bmp = win32ui.CreateCompatibleBitmap(dc_obj, w, h) mem_dc.SelectObject(bmp) # 3代表同时渲染窗口的非客户区和客户区内容,兼容性最好 win32gui.PrintWindow(game_hwnd, mem_dc.GetSafeHdc(), 3) # 转成PIL图像方便后续做图像识别 bmp_info = bmp.GetInfo() bmp_bits = bmp.GetBitmapBits(True) img = Image.frombuffer("RGB", (bmp_info["bmWidth"], bmp_info["bmHeight"]), bmp_bits, "raw", "BGRX", 0, 1) # 释放GDI资源,否则长时间运行会内存泄漏 dc_obj.DeleteDC() mem_dc.DeleteDC() win32gui.ReleaseDC(game_hwnd, hdc) win32gui.DeleteObject(bmp.GetHandle()) return img
- 部分游戏最小化后会暂停渲染逻辑,这种情况不需要真的最小化窗口,脚本启动时调用
win32gui.SetWindowPos(game_hwnd, None, -10000, -10000, 窗口宽度, 窗口高度, 0)把窗口移到屏幕显示范围外,视觉上和最小化完全一致,不占用屏幕空间,也不会影响你正常使用电脑,还能保证游戏正常渲染。
权限配置
不需要额外写代码配置权限,注意两点即可:
- 右键点击PyCharm图标,选择「以管理员身份运行」,从PyCharm启动的脚本默认就会继承管理员权限,拥有完整PC访问权限
- 脚本和游戏的权限要对齐:如果游戏是管理员权限启动,脚本也必须用管理员权限运行,否则Windows会拦截脚本发给游戏的窗口消息,导致操作失效
新手避坑
- 所有键鼠操作必须加随机延迟,固定间隔的操作极易被反作弊标记为机器人
- DirectX全屏独占模式下的游戏不响应win32消息,把游戏改成窗口化/无边框窗口模式即可
- 新手不要尝试读写游戏内存的实现方式,极易触发反作弊封号,先从纯消息模拟的逻辑练手
内容的提问来源于stack exchange,提问作者a newbie in programming
相关产品推荐
相关产品推荐

