commit 8960436379ae154351d93a3d7644901ad5d8365b Author: Ke Date: Thu Apr 2 14:54:45 2026 +0800 添加窗口钓鱼自动化脚本 - 实现窗口识别和激活功能 - 添加钓鱼和收杆消息发送 - 支持可配置时间间隔和循环次数 - 包含完整的日志记录和错误处理 - 提供测试模式和详细文档 - 添加.gitignore和requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31cd698 --- /dev/null +++ b/.gitignore @@ -0,0 +1,49 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdk/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Virtual environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Logs +*.log +fishing_bot.log + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# System +.DS_Store +Thumbs.db + +# Claude Code +.claude/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c89543 --- /dev/null +++ b/README.md @@ -0,0 +1,136 @@ +# 窗口钓鱼自动化脚本 + +这是一个用于自动化钓鱼操作的Python脚本,可以识别指定窗口并循环发送钓鱼和收杆消息。 + +## 功能特点 + +- 自动查找并激活目标窗口 +- 发送钓鱼和收杆消息(可自定义按键) +- 时间间隔可配置 +- 支持有限循环或无限循环 +- 完整的日志记录 +- 错误处理和重试机制 + +## 系统要求 + +- Python 3.6+ +- Windows系统(支持macOS/Linux但可能需要调整) + +## 安装依赖 + +```bash +pip install -r requirements.txt +``` + +或者手动安装: + +```bash +pip install pyautogui pygetwindow +``` + +## 使用方法 + +### 基本使用 + +```bash +# 使用默认设置(窗口标题包含"魔兽世界",间隔5秒,无限循环) +python main.py + +# 指定窗口标题和间隔 +python main.py --window "游戏窗口" --interval 10.0 + +# 指定循环次数 +python main.py --window "游戏窗口" --cycles 100 + +# 测试模式(检查功能是否正常) +python main.py --test +``` + +### 命令行参数 + +| 参数 | 简写 | 默认值 | 说明 | +|------|------|--------|------| +| `--window` | `-w` | `"魔兽世界"` | 目标窗口标题(支持部分匹配) | +| `--interval` | `-i` | `5.0` | 钓鱼和收杆之间的时间间隔(秒) | +| `--cycles` | `-c` | `0` | 循环次数(0表示无限循环) | +| `--test` | `-t` | `False` | 测试模式,只运行一个周期并显示详细信息 | + +### 自定义按键 + +如果需要修改发送钓鱼/收杆消息的按键,请编辑 `main.py` 文件中的以下方法: + +1. `send_fishing_message()` - 默认按 'F' 键 +2. `send_reel_message()` - 默认按空格键 + +可以修改为其他按键,例如: + +```python +# 改为按 '1' 键 +pyautogui.press('1') + +# 组合键 +pyautogui.hotkey('ctrl', 'f') + +# 鼠标点击 +pyautogui.click(x=100, y=200) +``` + +## 稳定性验证 + +脚本包含以下稳定性措施: + +1. **错误处理**:所有关键操作都有try-catch保护 +2. **日志记录**:详细日志记录到文件和终端 +3. **窗口重试**:每次循环都会重新查找窗口,避免窗口丢失 +4. **用户中断**:支持Ctrl+C安全退出 +5. **资源管理**:循环间有短暂暂停,避免CPU占用过高 + +### 验证方法 + +1. **功能测试**: + ```bash + python main.py --test + ``` + 检查是否能正确找到窗口、激活窗口。 + +2. **短期运行测试**: + ```bash + python main.py --cycles 10 --interval 2 + ``` + 运行10个周期,观察是否有错误。 + +3. **日志检查**: + 查看 `fishing_bot.log` 文件,确认没有异常错误。 + +4. **压力测试**: + ```bash + # 长时间运行(如1000个周期) + python main.py --cycles 1000 --interval 5 + ``` + +## 注意事项 + +1. **窗口焦点**:脚本需要激活目标窗口,期间不要操作鼠标键盘 +2. **时间间隔**:根据实际游戏需要调整间隔时间 +3. **防检测**:某些游戏禁止自动化,使用前请了解游戏规则 +4. **分辨率**:脚本不依赖于屏幕坐标,但窗口需要可见 + +## 故障排除 + +### 找不到窗口 +- 确认窗口标题正确 +- 窗口是否最小化或隐藏 +- 尝试使用部分标题匹配 + +### 按键不起作用 +- 确认游戏窗口处于激活状态 +- 检查游戏按键设置 +- 尝试增加激活后的等待时间 + +### 权限问题 +- 以管理员身份运行(某些游戏需要) +- 关闭杀毒软件或防火墙的干扰 + +## 许可证 + +MIT License \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..b79b7a2 --- /dev/null +++ b/main.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python3 +""" +窗口钓鱼自动化脚本 +功能:识别指定窗口,循环发送钓鱼和收杆消息,时间间隔相等 +""" + +import time +import logging +import sys +from typing import Optional + +# 尝试导入自动化库,如果缺失则提示安装 +try: + import pyautogui + import pygetwindow as gw +except ImportError as e: + print(f"缺少依赖库: {e}") + print("请使用 pip install pyautogui pygetwindow 安装") + sys.exit(1) + +# 配置日志 +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler('fishing_bot.log', encoding='utf-8'), + logging.StreamHandler() + ] +) +logger = logging.getLogger(__name__) + +class FishingBot: + def __init__(self, window_title: str, interval: float = 5.0): + """ + 初始化钓鱼机器人 + + Args: + window_title: 窗口标题(支持部分匹配) + interval: 钓鱼和收杆之间的时间间隔(秒) + """ + self.window_title = window_title + self.interval = interval + self.running = False + + def find_window(self) -> Optional[gw.Window]: + """ + 查找包含指定标题的窗口 + + Returns: + 找到的窗口对象,如果未找到则返回None + """ + try: + windows = gw.getWindowsWithTitle(self.window_title) + if windows: + logger.info(f"找到窗口: {windows[0].title}") + return windows[0] + else: + logger.warning(f"未找到包含标题 '{self.window_title}' 的窗口") + return None + except Exception as e: + logger.error(f"查找窗口时出错: {e}") + return None + + def activate_window(self, window: gw.Window) -> bool: + """ + 激活指定窗口 + + Args: + window: 窗口对象 + + Returns: + 是否成功激活 + """ + try: + window.activate() + time.sleep(0.5) # 等待窗口激活 + logger.info(f"已激活窗口: {window.title}") + return True + except Exception as e: + logger.error(f"激活窗口时出错: {e}") + return False + + def send_fishing_message(self) -> bool: + """ + 发送钓鱼消息 + + Returns: + 是否成功发送 + """ + try: + # 这里根据实际需要修改发送方式 + # 示例:模拟按下'F'键(常见游戏钓鱼键) + pyautogui.press('f') + logger.info("发送钓鱼消息") + return True + except Exception as e: + logger.error(f"发送钓鱼消息时出错: {e}") + return False + + def send_reel_message(self) -> bool: + """ + 发送收杆消息 + + Returns: + 是否成功发送 + """ + try: + # 这里根据实际需要修改发送方式 + # 示例:模拟按下空格键(常见游戏收杆键) + pyautogui.press('space') + logger.info("发送收杆消息") + return True + except Exception as e: + logger.error(f"发送收杆消息时出错: {e}") + return False + + def run_cycle(self) -> bool: + """ + 运行一个完整的钓鱼周期 + + Returns: + 周期是否成功完成 + """ + # 查找窗口 + window = self.find_window() + if not window: + logger.error("无法找到目标窗口,跳过本次周期") + return False + + # 激活窗口 + if not self.activate_window(window): + logger.error("无法激活窗口,跳过本次周期") + return False + + # 发送钓鱼消息 + if not self.send_fishing_message(): + logger.error("发送钓鱼消息失败,跳过本次周期") + return False + + # 等待间隔 + logger.info(f"等待 {self.interval} 秒...") + time.sleep(self.interval) + + # 发送收杆消息 + if not self.send_reel_message(): + logger.error("发送收杆消息失败") + return False + + return True + + def start(self, cycles: int = 0): + """ + 启动钓鱼机器人 + + Args: + cycles: 循环次数,0表示无限循环 + """ + self.running = True + cycle_count = 0 + + logger.info(f"开始钓鱼机器人,窗口标题: '{self.window_title}', 间隔: {self.interval}秒") + + try: + while self.running: + cycle_count += 1 + logger.info(f"开始第 {cycle_count} 个周期") + + success = self.run_cycle() + + if success: + logger.info(f"第 {cycle_count} 个周期完成") + else: + logger.warning(f"第 {cycle_count} 个周期失败") + + # 如果指定了循环次数且已达到,则停止 + if cycles > 0 and cycle_count >= cycles: + logger.info(f"已完成指定的 {cycles} 个周期") + break + + # 周期之间的短暂暂停,避免CPU占用过高 + time.sleep(1) + + except KeyboardInterrupt: + logger.info("用户中断执行") + except Exception as e: + logger.error(f"运行时发生未预期错误: {e}") + finally: + self.running = False + logger.info("钓鱼机器人已停止") + + def stop(self): + """停止钓鱼机器人""" + self.running = False + logger.info("停止信号已发送") + +def main(): + """主函数""" + import argparse + + parser = argparse.ArgumentParser(description='窗口钓鱼自动化脚本') + parser.add_argument('--window', '-w', default='魔兽世界', + help='目标窗口标题(支持部分匹配)') + parser.add_argument('--interval', '-i', type=float, default=5.0, + help='钓鱼和收杆之间的时间间隔(秒)') + parser.add_argument('--cycles', '-c', type=int, default=0, + help='循环次数(0表示无限循环)') + parser.add_argument('--test', '-t', action='store_true', + help='测试模式:只运行一个周期并显示详细信息') + + args = parser.parse_args() + + # 创建机器人实例 + bot = FishingBot(args.window, args.interval) + + if args.test: + logger.info("=== 测试模式 ===") + logger.info(f"窗口标题: {args.window}") + logger.info(f"间隔: {args.interval}秒") + + # 测试窗口查找 + window = bot.find_window() + if window: + logger.info(f"✓ 找到窗口: {window.title}") + else: + logger.error("✗ 未找到窗口") + return + + # 测试激活 + if bot.activate_window(window): + logger.info("✓ 窗口激活成功") + else: + logger.error("✗ 窗口激活失败") + return + + logger.info("测试完成,请检查日志确认功能正常") + return + + # 启动机器人 + try: + bot.start(args.cycles) + except KeyboardInterrupt: + logger.info("脚本被用户中断") + except Exception as e: + logger.error(f"脚本执行出错: {e}") + return 1 + + return 0 + +if __name__ == "__main__": + sys.exit(main()) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5dc87a7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pyautogui==0.9.54 +pygetwindow==0.0.9 +# 如果需要跨平台支持,可以添加以下库 +# pynput==1.7.6 \ No newline at end of file