252 lines
7.3 KiB
Python
252 lines
7.3 KiB
Python
#!/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:
|
||
# 这里根据实际需要修改发送方式
|
||
# 示例:输入"钓鱼"文字
|
||
pyautogui.typewrite('钓鱼')
|
||
time.sleep(0.1)
|
||
logger.info("发送钓鱼消息")
|
||
return True
|
||
except Exception as e:
|
||
logger.error(f"发送钓鱼消息时出错: {e}")
|
||
return False
|
||
|
||
def send_reel_message(self) -> bool:
|
||
"""
|
||
发送收杆消息
|
||
|
||
Returns:
|
||
是否成功发送
|
||
"""
|
||
try:
|
||
# 这里根据实际需要修改发送方式
|
||
# 示例:输入"收杆"文字
|
||
pyautogui.typewrite('收杆')
|
||
time.sleep(0.1)
|
||
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()) |