以4399小游戏为例:
import pyautogui
import keyboard
import time
import random
import logging
from PIL import ImageGrab
import os
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# 游戏配置
GAME_DURATION = 60 # 游戏时长(秒)
MIN_CLICK_INTERVAL = 0.1 # 最小点击间隔(秒)
MAX_CLICK_INTERVAL = 0.3 # 最大点击间隔(秒)
CONFIDENCE_THRESHOLD = 0.75 # 图像匹配置信度阈值
DEBUG_SCREENSHOT = "debug_screenshot.png" # 调试用屏幕截图
# 图片路径(请将这些图片放在脚本同目录下)
START_BUTTON_IMAGE = "start.png" # 开始游戏按钮
MOLE_IMAGE = "dishu.png" # 地鼠图片
# 提示:请先截取这两张图片,确保图片清晰且背景单一
def check_images():
"""检查所需图片文件是否存在"""
for image_path in [START_BUTTON_IMAGE, MOLE_IMAGE]:
if not os.path.exists(image_path):
error_msg = f"找不到图片文件: {image_path}\n"
error_msg += "请先截取游戏中的开始按钮和地鼠,保存为同名图片文件"
logger.error(error_msg)
raise FileNotFoundError(error_msg)
logger.info("所有图片文件已找到,准备开始游戏...")
def find_and_click_image(image_path, confidence=CONFIDENCE_THRESHOLD, debug=False):
"""在屏幕上查找指定图片并点击"""
try:
location = pyautogui.locateCenterOnScreen(image_path, confidence=confidence)
if location:
# 添加随机偏移模拟人类操作
offset_x = random.randint(-3, 3)
offset_y = random.randint(-3, 3)
click_x, click_y = location[0] + offset_x, location[1] + offset_y
pyautogui.click(click_x, click_y)
logger.info(f"点击 {image_path} 成功,位置: ({click_x}, {click_y})")
return True
else:
if debug:
# 保存截图用于调试
ImageGrab.grab().save(DEBUG_SCREENSHOT)
logger.info(f"未找到图片,已保存调试截图: {DEBUG_SCREENSHOT}")
return False
except Exception as e:
logger.error(f"查找图片 {image_path} 时出错: {e}")
return False
def start_game():
"""定位并点击开始游戏按钮"""
logger.info("正在查找开始游戏按钮...")
for attempt in range(15):
if find_and_click_image(START_BUTTON_IMAGE):
logger.info("已点击开始游戏按钮,等待游戏加载...")
time.sleep(1) # 等待游戏界面加载
return True
time.sleep(0.5)
logger.error("未找到开始按钮,请检查图片或游戏窗口位置")
return False
def play_game():
"""主游戏循环:持续查找并点击地鼠"""
start_time = time.time()
click_count = 0
logger.info(f"游戏开始!自动点击地鼠中(持续{GAME_DURATION}秒)...")
logger.info("按ESC键可随时退出游戏")
while time.time() - start_time < GAME_DURATION:
# 检测退出键
if keyboard.is_pressed('esc'):
logger.info("检测到ESC键,退出游戏...")
break
# 查找并点击地鼠
if find_and_click_image(MOLE_IMAGE):
click_count += 1
# 随机间隔,模拟人类反应
interval = random.uniform(MIN_CLICK_INTERVAL, MAX_CLICK_INTERVAL)
time.sleep(interval)
logger.info(f"游戏结束!共点击地鼠 {click_count} 次")
return click_count
def main():
"""主程序流程"""
try:
# 初始化设置
pyautogui.FAILSAFE = True # 安全机制:鼠标移到左上角可终止程序
logger.info("=== 4399打地鼠游戏自动化脚本 ===")
# 提示用户准备
print("请在5秒内将浏览器窗口调整到合适位置,确保游戏界面完全可见")
for i in range(5, 0, -1):
print(f"倒计时: {i}...")
time.sleep(1)
# 检查图片并开始游戏
check_images()
if start_game():
play_game()
except Exception as e:
logger.error(f"程序异常终止: {str(e)}")
# 保存最后截图用于调试
if os.path.exists(DEBUG_SCREENSHOT):
os.remove(DEBUG_SCREENSHOT)
ImageGrab.grab().save(DEBUG_SCREENSHOT)
logger.info(f"已保存异常截图: {DEBUG_SCREENSHOT}")
if __name__ == "__main__":
main()
一、整体架构与流程
脚本采用模块化设计,主要包含以下几个功能模块:
- 初始化与配置:设置游戏参数、图片路径和日志系统
- 图片检测模块:核心识别功能,查找并点击目标图片
- 游戏控制模块:处理开始游戏和主游戏循环逻辑
- 用户交互模块:支持 ESC 键退出和安全机制
整体流程如下:
初始化设置 -> 等待用户调整窗口 -> 检查图片文件 -> 点击开始按钮 -> 进入游戏循环 -> 持续识别并点击地鼠 -> 游戏结束统计结果
二、核心功能详解
1. 图片识别与点击(核心功能)
def find_and_click_image(image_path, confidence=CONFIDENCE_THRESHOLD, debug=False):
"""在屏幕上查找指定图片并点击"""
try:
location = pyautogui.locateCenterOnScreen(image_path, confidence=confidence)
if location:
# 添加随机偏移模拟人类操作
offset_x = random.randint(-3, 3)
offset_y = random.randint(-3, 3)
click_x, click_y = location[0] + offset_x, location[1] + offset_y
pyautogui.click(click_x, click_y)
return True
else:
if debug:
ImageGrab.grab().save(DEBUG_SCREENSHOT)
return False
except Exception as e:
logger.error(f"查找图片 {image_path} 时出错: {e}")
return False
技术原理:使用
pyautogui.locateCenterOnScreen
进行模板匹配,通过对比截图与目标图片的像素相似度定位元素关 键参数:
confidence
:置信度阈值(0-1),值越高要求匹配度越高offset_x/offset_y
:随机偏移量,模拟人类点击时的微小误差调试机制:未找到图片时保存全屏截图,便于分析识别失败原因
2. 游戏控制流程
def start_game():
"""定位并点击开始游戏按钮"""
for attempt in range(15):
if find_and_click_image(START_BUTTON_IMAGE):
time.sleep(1) # 等待游戏加载
return True
time.sleep(0.5)
return False
def play_game():
"""主游戏循环:持续查找并点击地鼠"""
start_time = time.time()
click_count = 0
while time.time() - start_time < GAME_DURATION:
if keyboard.is_pressed('esc'): break # ESC键退出
if find_and_click_image(MOLE_IMAGE):
click_count += 1
time.sleep(random.uniform(MIN_CLICK_INTERVAL, MAX_CLICK_INTERVAL))
开始游戏逻辑:尝试 15 次点击开始按钮,每次间隔 0.5 秒,适应网页加载延迟
游 戏循环:
- 计时控制游戏时长(
GAME_DURATION=60秒
)- 实时检测 ESC 键,支持手动中断
- 随机间隔(0.1-0.3 秒)模拟人类反应速度,避免固定频率被游戏检测
3. 安全与交互设计
def main():
pyautogui.FAILSAFE = True # 鼠标移到左上角终止程序
print("请在5秒内调整窗口...")
for i in range(5, 0, -1): print(f"倒计时: {i}..."); time.sleep(1)
双重安全 机制:
pyautogui.FAILSAFE
:鼠标移到屏幕左上角时强制终止程序- ESC 键检测:游戏中随时按 ESC 退出
用户交互:倒计时提示用户调整窗口,确保游戏区域可见
三、关键技术点与优化策略
1. 图像识别优化
- 置信度阈值调节:
CONFIDENCE_THRESHOLD=0.75
是平衡准确率和识别率的默认值
- 若频繁误判(点击到非地鼠区域):提高阈值(如 0.85)
- 若识别困难:降低阈值(如 0.65),或优化截图清晰度
- 截图范围优化:默认识别全屏,若游戏区域固定,可通过
region=(x,y,width,height)
参数限定搜索范围,提高效率
2. 模拟人类操作
随机偏移点击:
random.randint(-3, 3)
使每次点击位置略有不同,避免机械点击模式随机时间间隔:
ran dom.uniform(0.1, 0.3)
模拟人类反应时间差异,比固定间隔更逼真
3. 错误处理与调试
日志系统:记录关键操作和错误,便于追溯问题
调试截图:未找到图片时保存
debug_screenshot.png
,帮助确认游戏元素是否在屏幕中异常捕获:使用
try-except
块防止单个错误导致程序崩溃
四、使用前的必要准备
- 环境安装:
pip install pyautogui keyboard pillow
- 图片准备:
- 截取 4399 打地鼠游戏的开始按钮和地鼠图片,保存为:
start_button.png
(建议包含完整按钮,背景单一)mole.png
(地鼠完全弹出的状态,分辨率≥50x50)
- 截取 4399 打地鼠游戏的开始按钮和地鼠图片,保存为:
- 浏览器设置:
调整浏览器窗口大小,确保游戏区域完整显示且无遮挡
建议 使用全屏模式或固定窗口位置,避免元素位置
五、常见问题与解决方案
问题现象 | 可能原因 | 解决方案 |
---|---|---|
脚本运行后无反应 | 未找到图片 | 1. 检查图片路径是否正确 2. 降低 CONFIDENCE_THRESHOLD 值3. 查看 debug_screenshot.png 确认游戏元素是否在截图中 |
点击位置偏移 | 屏幕分辨率或缩放导致坐标偏差 | 1. 关闭浏览器缩放(保持 100%) 2. 调整 offset_x/offset_y 偏移量 |
程序异常退出 | 图片格式不支持或内存错误 | 1. 使用 PNG/JPG 格式图片 2. 检查 pyautogui 版本是否兼容 |
补充:多类型地鼠
# 示例:优先点击高分值地鼠
if find_and_click_image("gold_mole.png"):
pass # 点击金老鼠
elif find_and_click_image("normal_mole.png"):
pass # 点击普通老鼠
若游戏中有不同分值的地鼠,可准备多张图片并设置优先级
这个脚本通过图像识别技术实现了游戏自动化,核心在于pyautogui
的模板匹配功能,同时通过随机化和异常处理提升了实用性和稳定性。根据实际游戏场景调整参数后,可有效提高打地鼠效率。