
经常有朋友跑来问我Python能不能做个EVE自动化挖矿我的回答一直是能做但前提是你得先搞清楚你要的是“学原理”还是“拿脚本挂矿”。这篇分享会把模拟点击原理从头到尾拆开配套一个“截屏—识别—点击—循环”的完整实现骨架适合想入门Python GUI自动化、图像识别和游戏脚本原理的读者也适合正在折腾RPA办公自动化的朋友。标题里提到的EVE更多是当演示场景用。但我也得先把丑话说在前面EVE的用户协议明确禁止第三方自动化工具脚本一旦被官方行为检测盯上轻则警告重则永久封号。所以这篇文章侧重的是模拟点击和图像识别这套通用技术不是教你造一个“绝对安全”的外挂。代码你可以拿去学习原理但别拿正式账号当实验品原因我会在最后一部分详细讲。1. 自动化挖矿的整体设计先理清脚本到底要做什么1.1 一个挖矿脚本的完整闭环很多人一开始就想写代码但老手都会先做一件事把人工挖矿的完整操作流程列出来然后再想哪些环节能交给程序。手动挖矿大概是这样的进入小行星带靠近矿体右键选中目标点击锁定确保自己没有被怪揍开启采矿器等货柜舱满了打开星域图跳回空间站卸货再跳回来继续。整个过程听起来简单但包含了很多“感知”和“决策”怎么判断货柜满了怎么知道当前有没有被怪绕自动化脚本要替代的正是这些“判断与操作”。它本身没有眼睛所有感知都来自截屏它没有手所有操作都靠模拟鼠标键盘。所以一个完整的自动化挖矿脚本闭环是截屏 → 识别目标位置和状态 → 模拟点击或按键 → 等待 → 再次截屏 → 重复。难点不在于“操作”本身而在于“感知”。只要你把“识别当前画面里有什么”这件事做通后面的事情就顺理成章了。1.2 同一种需求三条技术路线游戏自动化的常见做法有三类我直接列个表对比一下技术路线原理难度风险适用场景内存读写读取游戏进程内存获取坐标、资源、货柜容量等数据高需要逆向分析极易被反作弊检测修改内存风险极高单机游戏、自研程序演示封包模拟分析网络协议伪造客户端与服务器之间的数据包极高需要抓包加解密在线游戏必死属于重度违规协议学习几乎不适合游戏图像识别模拟点击截屏识别画面元素用鼠标键盘事件去操作中低适合入门违反游戏用户协议报行为检测风险办公自动化、自动化测试、学习演示三条路里图像识别加模拟点击是门槛最低、通用性最强的一条。它不修改游戏文件、不读内存、不碰网络协议单纯从“屏幕画面上看”来模拟一个玩家的操作。这也是为什么教程满天飞因为它的技术栈完全来自正常的桌面自动化领域。1.3 模拟点击方案的优势与短板先说优势。这套方案不需要逆向工程也不需要面对游戏封包的加密和压缩游戏更新版本时只要UI变化不大代码甚至不用改。更关键的是这套技术几乎是全行业通用的你今天用来写一个“自动打开网页截屏保存”的小工具明天就能用到“自动识别验证码点击”的RPA流程里不会被锁死在某个游戏上。短板也很明显。速度慢每一次截屏加识别至少花费0.1到0.3秒而且识别精度受分辨率和UI缩放影响很大。长时间运行还会因为弹窗、遮挡、视角变化导致识别失效。最重要的是脚本的行为模式跟真人完全不同服务器端可以用行为分析识别出“机械式操作”这跟你怎么写代码没关系。它本质上还是“模拟人”不是“变成人”。2. 核心细节解析模拟点击和屏幕识别怎么落地2.1 鼠标键盘模拟的两条路pyautogui与Win32 APIPython里做鼠标键盘模拟最常见的库是pyautogui因为它简单几行代码就能移动鼠标、点击、输入文字。但你如果直接拿到EVE这种DirectX游戏里用十有八九会碰到一个问题鼠标动了游戏却没反应。原因在于pyautogui底层用的是Windows的SendInput换一种方式发送输入事件某些DirectX游戏不会完整处理这类“合成事件”。我实测下来最稳妥的办法是用Win32 API直接调mouse_event或SetCursorPos或者直接用pydirectinput这个专门为DirectX游戏封装的第三方库。给你看一眼Win32 API的写法import ctypes # 移动鼠标到指定坐标 ctypes.windll.user32.SetCursorPos(960, 540) # 模拟左键按下和抬起 ctypes.windll.user32.mouse_event(0x0002, 0, 0, 0, 0) # MOUSEEVENTF_LEFTDOWN ctypes.windll.user32.mouse_event(0x0004, 0, 0, 0, 0) # MOUSEEVENTF_LEFTUP这里0x0002和0x0004是Windows定义的鼠标事件常量分别表示左键按下和左键抬起。实际写脚本时我更倾向于先试pydirectinput它的接口跟pyautogui几乎一样但底层用的是SendInput对DirectX游戏兼容性好不少。2.2 屏幕截图与目标定位模板匹配模拟点击的前提是知道“往哪点”这就需要对屏幕画面做截图和目标定位。我常用的组合是Pillow截屏加OpenCV的模板匹配。流程很简单先把屏幕截下来转成灰度图再把提前截好的“目标素材”也转成灰度图用cv2.matchTemplate遍历整张屏幕计算相似度找到相似度最高的位置如果相似度超过阈值就认为找到了目标。打个比方这就像在一张地图里找一块拼图碎片OpenCV帮你把每个位置的相似分数都算出来然后取最高分的位置。模板匹配有个关键参数叫阈值threshold我一般默认设0.8。因为实际画面里光照、抗锯齿、UI叠加都会让相似度下降设太高会找不到设太低会乱点需要根据实际情况调。2.3 游戏窗口、坐标系与DPI缩放这里是我踩坑最惨的地方。脚本移动鼠标用的坐标是以整个屏幕左上角为原点单位是像素。但如果Windows缩放设置是125%或150%或者游戏跑在全屏模式坐标就会对不上。解决方案是启动脚本时先强制进程感知DPIimport ctypes try: ctypes.windll.user32.SetProcessDPIAware() except AttributeError: pass然后尽量把游戏设置为“无边框窗口化”不要用“全屏独占”。因为全屏模式下游戏画面不走GDI通用绘制某些截屏接口会拿到黑屏无边框窗口化既能截屏坐标也更直观。另外还要注意如果脚本和游戏分别跑在不同的显示器上pyautogui的坐标可能是负数因为Windows允许鼠标移动到主屏幕左侧的副屏上。多显示器场景一定要先确认你自己的坐标系。2.4 操作节奏与随机延迟新手写脚本最喜欢写time.sleep(3)意思是等3秒再执行下一步。但固定间隔是一个非常危险的信号不仅看起来机械实际也容易因为网络延迟导致操作还没生效就进入了下一步。我个人的做法是给所有等待时间套一个随机范围import random import time def human_delay(min_sec1.5, max_sec2.5): time.sleep(random.uniform(min_sec, max_sec))注意这里不是为了教你逃避行为检测而是为了减少脚本误操作。真人操作本来就不可能每次都是精确的1.5秒随机延时能让脚本在遇到轻微卡顿时更不容易乱套。对于自用的RPA脚本这也是提升稳定性的常见手段。3. 实操过程从零写一个挖矿脚本骨架3.1 环境准备先准备好Python环境3.9、3.10、3.11都行我常用3.10。然后安装依赖pip install pyautogui opencv-python numpy pillow pydirectinput如果你是第一次装opencv-python可能需要稍等一会儿因为它体积比较大。实际用到的模块也不多就cv2、numpy、pyautogui这三个是核心。3.2 准备目标模板这里的准备很关键。打开游戏调整好视角和UI缩放把小行星带里的目标矿体截图保存成一张小图比如asteroid.png。注意模板不要截太大截取40x40到80x80像素的核心特征区域就够了。截图主题越“特别”越好最好带点纹理轮廓。如果整片都是漆黑的太空模板匹配容易失败。你可以把目标锁定在矿体表面有光照反射的区域识别率会高很多。3.3 第一步先写一个“截屏—识别—点击”的最小例子我建议先不要让脚本干实事而是写一个最小例子验证环境。只要能在屏幕上找到模板并打印出坐标就说明整条链路通了。import cv2 import numpy as np import pyautogui def find_target(template_path, threshold0.8): screenshot pyautogui.screenshot() screen cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR) screen_gray cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY) template cv2.imread(template_path, cv2.IMREAD_GRAYSCALE) result cv2.matchTemplate(screen_gray, template, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc cv2.minMaxLoc(result) if max_val threshold: h, w template.shape center_x max_loc[0] w // 2 center_y max_loc[1] h // 2 return (center_x, center_y), max_val return None, max_val center, confidence find_target(asteroid.png) if center: print(f找到目标坐标{center}置信度{confidence:.3f}) else: print(f未找到目标最高置信度{confidence:.3f})这里有两个细节值得注意。第一pyautogui.screenshot()返回的是Pillow图像转成OpenCV能处理的格式需要先转成numpy数组再换颜色通道。第二cv2.matchTemplate的TM_CCOEFF_NORMED方法返回的置信度在-1到1之间越接近1越相似。如果你跑完发现坐标打印出来了恭喜自动化管线的核心已经打通了。剩下的就是围绕这个循环加业务逻辑。3.4 第二步组装挖矿循环我上面说过识别只是“眼睛”最终要形成“循环”。一个典型挖矿流程的伪代码是这样的锁定目标靠近右键锁定开启采矿器等待货柜满回站卸货再跳回来。但为了演示模拟点击原理我用一个简化的方案循环找矿体找到就点击没找到就稍等后重新截屏。同时加入手动停止机制避免脚本失控。import random import time import pyautogui import keyboard pyautogui.FAILSAFE True # 鼠标快速移到左上角可强制中断 def human_delay(min_sec1.0, max_sec2.0): time.sleep(random.uniform(min_sec, max_sec)) def mining_loop(max_round50): round_count 0 while round_count max_round: if keyboard.is_pressed(q): print(手动停止) break center, confidence find_target(asteroid.png, threshold0.7) if center: pyautogui.moveTo(center[0], center[1], duration0.2) pyautogui.click() print(f第 {round_count 1} 轮点击 {center}) human_delay(2.0, 3.5) else: print(没找到目标1秒后重试) time.sleep(1) round_count 1 mining_loop()这段代码只有一个“找到矿体就点击”的行为真正到游戏里还需要右键菜单选择“锁定”之类的操作。你可以把它当成一个模板按需在“点击后弹出来的菜单”里再套一层模板识别点击菜单项。思路是一样的每多一个步骤就是多一次截屏识别加点击。3.5 参数调优与跑批验证写完之后先别直接进游戏我建议用录屏回放的方式验证。把之前录好的游戏画面用播放器全屏播放然后运行脚本看它能不能稳定识别到目标。这个方法不会封号还能快速调阈值和延时参数。调参数的时候注意几个原则阈值太高找不到就降低到0.7试试截图区域太大导致匹配慢就缩小模板识别到的坐标总是偏左或偏上大概率是DPI缩放或者模板尺寸算错检查一下w // 2和h // 2的换算。4. 常见问题与排查技巧实录4.1 模板匹配找不到目标怎么办这类问题问的人最多。我总结下来原因基本集中在三处一是模板本身截得不好二是阈值设太高三是画面里目标被遮挡或者视角变了。排查思路是先把没找到目标时的截图保存下来画一个红框标记出最高匹配位置这样能直观看到OpenCV到底把哪里判定为“最相似”。如果真的画在了一个毫不相干的位置说明模板特征不够明显换一张更清晰的模板。如果画的位置是正确的但置信度达不到阈值就把阈值调低到0.6或0.7。一个很多人忽略的细节是游戏里的抗锯齿和动态光影会让同一块矿体在不同角度下长得不一样。所以模板尽量选择光照变化小的局部特征而不是一整块石头。如果你发现不同时间段稳定性差很多建议固定游戏内视角尽量减少环境变量。4.2 鼠标点击没反应或坐标错位点击没反应优先怀疑输入事件类型。先用pydirectinput替换pyautogui的点击大多数DirectX游戏都能解决。还是不行就用管理员权限运行Python脚本因为如果游戏本身以管理员权限运行普通权限脚本发出去的模拟输入会被系统拦掉。坐标错位的问题90%是DPI缩放。我见过最典型的案例系统缩放150%但脚本没有调用SetProcessDPIAware()结果识别到的坐标全部偏移。在脚本最开头加好DPI感知再配合无边框窗口化基本能解决。多显示器用户还要注意pyautogui.screenshot()默认只截主屏如果游戏在副屏上需要传region参数指定区域。4.3 截屏黑屏与权限问题全屏独占模式下截屏黑屏是DirectX游戏的常规操作。最省事的办法是把游戏改成“无边框窗口化”或“窗口模式”这样Windows桌面合成器就能正常提供画面给GDI接口截图。另外用远程桌面连接去跑脚本时截屏也可能拿到黑屏或者非常卡顿的画面因为远程会话的桌面渲染和本地不一样。我的建议是本地跑或者用虚拟显示器设备别用远程桌面硬刚。4.4 关于自动化脚本的边界与封号风险这段话是我最想认真写的。模拟点击这套技术本身是中性的它是RPA、自动化测试、辅助工具的基础但一旦用在EVE这类在线游戏的正式账号上性质就不一样了。EVE官方的用户协议里写得很清楚禁止使用任何第三方自动化程序来替代人工操作。服务器会记录你每次点击的坐标、时间间隔、运行动作序列然后用行为分析判断是不是脚本。这种检测跟你用没用内存修改器无关单纯是“行为太规律”就可能被标记。随机延迟能增加一点迷惑性但解决不了根本问题因为真人操作是带情绪和反应的脚本做不到。所以我的立场是这篇文章的所有代码你拿去研究原理、练手桌面自动化、做本地演示都没问题但不要拿去跑EVE正式账号。我自己也只在本地开发的测试demo里验证过这套流程真正把模拟点击用好是在给朋友做银行回单自动下载工具的时候那个场景才是它发光的地方。结尾最后分享一点个人体会。模拟点击加模板匹配这套组合看上去是游戏脚本的入门套路但真正学通之后你会发现它的应用面远不止游戏。我后来帮朋友做过一个报表自动归集的小工具就是靠截屏识别Excel里某个按钮然后自动点击几分钟干完了原来人工半小时的重复劳动。那瞬间你会觉得技术本身没有善恶关键看你怎么用它。如果你也想折腾这套技术建议先从最简单的demo开始写一个自动打开记事本输入文字再保存的脚本再进阶到识别屏幕图标并双击打开。基础扎实之后EVE挖矿这个课题对你来说就只是一个场景案例而不是目标本身了。这个内容后续还可以扩展的方向很多比如用OCR识别游戏内文本状态、用YOLO做目标检测代替模板匹配、把控制逻辑改成状态机等等。慢慢玩收获会比想象中大。