采矿记录.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import tkinter as tk
  2. from tkinter import ttk, scrolledtext
  3. import pyautogui
  4. import pyperclip
  5. import time
  6. import threading
  7. import csv
  8. import os
  9. import re
  10. from datetime import datetime
  11. class AutoClickerApp:
  12. def __init__(self, root):
  13. self.root = root
  14. self.root.title("自动点击采集工具")
  15. self.root.geometry("900x700")
  16. # 状态变量
  17. self.is_running = False
  18. self.thread = None
  19. self.stop_event = threading.Event()
  20. # 数据存储
  21. self.coord_data = [] # 存储CSV数据
  22. self.last_coords = [] # 存储每次采集到的坐标 (用于去重)
  23. self.setup_ui()
  24. self.load_csv_data()
  25. def setup_ui(self):
  26. # 控制按钮框架
  27. control_frame = tk.Frame(self.root)
  28. control_frame.pack(pady=10)
  29. self.start_btn = tk.Button(control_frame, text="开始", command=self.start_action,
  30. bg="green", fg="white", font=("Arial", 12), width=10)
  31. self.start_btn.pack(side=tk.LEFT, padx=5)
  32. self.stop_btn = tk.Button(control_frame, text="停止", command=self.stop_action,
  33. bg="red", fg="white", font=("Arial", 12), width=10)
  34. self.stop_btn.pack(side=tk.LEFT, padx=5)
  35. # 表格框架
  36. table_frame = tk.Frame(self.root)
  37. table_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)
  38. # 创建表格
  39. self.tree = ttk.Treeview(table_frame, columns=('x_range', 'y_range', 'collect_time'), show='headings', height=15)
  40. # 设置列
  41. self.tree.heading('x_range', text='X坐标范围')
  42. self.tree.heading('y_range', text='Y坐标范围')
  43. self.tree.heading('collect_time', text='采集时间')
  44. self.tree.column('x_range', width=150, anchor='center')
  45. self.tree.column('y_range', width=150, anchor='center')
  46. self.tree.column('collect_time', width=250, anchor='center')
  47. # 添加滚动条
  48. scrollbar = ttk.Scrollbar(table_frame, orient=tk.VERTICAL, command=self.tree.yview)
  49. self.tree.configure(yscrollcommand=scrollbar.set)
  50. self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
  51. scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  52. # 日志框架
  53. log_frame = tk.Frame(self.root)
  54. log_frame.pack(pady=10, padx=10, fill=tk.BOTH, expand=True)
  55. tk.Label(log_frame, text="日志:", font=("Arial", 10, "bold")).pack(anchor='w')
  56. self.log_text = scrolledtext.ScrolledText(log_frame, height=10, wrap=tk.WORD)
  57. self.log_text.pack(fill=tk.BOTH, expand=True)
  58. def load_csv_data(self):
  59. """加载CSV文件数据"""
  60. csv_file = "coordinates.csv"
  61. if not os.path.exists(csv_file):
  62. self.log_message(f"未找到 {csv_file} 文件,请创建示例文件")
  63. self.create_sample_csv()
  64. return
  65. try:
  66. with open(csv_file, 'r', encoding='utf-8') as file:
  67. csv_reader = csv.reader(file)
  68. self.coord_data = list(csv_reader)
  69. # 清空表格
  70. for item in self.tree.get_children():
  71. self.tree.delete(item)
  72. # 填充表格
  73. for row in self.coord_data:
  74. if len(row) >= 3:
  75. self.tree.insert('', 'end', values=(row[0], row[1], row[2]))
  76. self.log_message(f"成功加载 {len(self.coord_data)} 条坐标数据")
  77. except Exception as e:
  78. self.log_message(f"加载CSV文件失败: {str(e)}")
  79. def create_sample_csv(self):
  80. """创建示例CSV文件"""
  81. sample_data = [
  82. ['62-42', '225-73', ''],
  83. ['240-300', '100-150', ''],
  84. ['180-220', '50-90', '']
  85. ]
  86. try:
  87. with open('coordinates.csv', 'w', newline='', encoding='utf-8') as file:
  88. writer = csv.writer(file)
  89. writer.writerows(sample_data)
  90. self.log_message("已创建示例CSV文件: coordinates.csv")
  91. self.load_csv_data()
  92. except Exception as e:
  93. self.log_message(f"创建示例CSV文件失败: {str(e)}")
  94. def log_message(self, message):
  95. """添加日志消息"""
  96. timestamp = datetime.now().strftime("%H:%M:%S")
  97. self.log_text.insert(tk.END, f"[{timestamp}] {message}\n")
  98. self.log_text.see(tk.END)
  99. def update_table_time(self, x, y):
  100. """根据坐标更新表格中的时间"""
  101. try:
  102. x_float = float(x)
  103. y_float = float(y)
  104. # 从最后一行开始向前匹配(只匹配最新的)
  105. for i in range(len(self.coord_data) - 1, -1, -1):
  106. row = self.coord_data[i]
  107. if len(row) >= 2:
  108. # 解析X范围
  109. x_range = row[0].strip()
  110. if '-' in x_range:
  111. x_start, x_end = x_range.split('-')
  112. try:
  113. x_start = float(x_start.strip())
  114. x_end = float(x_end.strip())
  115. if x_start <= x_float <= x_end:
  116. # 解析Y范围
  117. y_range = row[1].strip()
  118. if '-' in y_range:
  119. y_start, y_end = y_range.split('-')
  120. y_start = float(y_start.strip())
  121. y_end = float(y_end.strip())
  122. if y_start <= y_float <= y_end:
  123. # 匹配成功,更新时间
  124. current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  125. row[2] = current_time
  126. # 更新表格显示
  127. children = self.tree.get_children()
  128. if i < len(children):
  129. self.tree.delete(children[i])
  130. self.tree.insert('', i, values=(row[0], row[1], row[2]))
  131. self.log_message(f"坐标 ({x_float}, {y_float}) 匹配成功,时间已更新为 {current_time}")
  132. return True
  133. except ValueError:
  134. continue
  135. self.log_message(f"坐标 ({x_float}, {y_float}) 未匹配到任何范围")
  136. return False
  137. except ValueError:
  138. self.log_message(f"坐标格式错误: {x}, {y}")
  139. return False
  140. def parse_clipboard_content(self, content):
  141. """解析剪贴板内容,提取坐标"""
  142. lines = content.strip().split('\n')
  143. found_coords = None
  144. # 查找"发现真武矿采集物坐标"的行
  145. for i, line in enumerate(lines):
  146. if '发现真武矿采集物坐标' in line:
  147. # 检查前一行是否包含"挖着了"
  148. if i > 0 and '挖着了' in lines[i-1]:
  149. # 提取坐标
  150. match = re.search(r'发现真武矿采集物坐标:([\d.]+),([\d.]+)', line)
  151. if match:
  152. x = match.group(1)
  153. y = match.group(2)
  154. found_coords = (x, y)
  155. self.log_message(f"发现有效坐标: {x}, {y}")
  156. break
  157. if found_coords:
  158. x, y = found_coords
  159. # 检查是否与上次采集的坐标相同(去重)
  160. if (x, y) not in self.last_coords:
  161. self.last_coords.append((x, y))
  162. # 只保留最近10条记录
  163. if len(self.last_coords) > 10:
  164. self.last_coords.pop(0)
  165. self.update_table_time(x, y)
  166. else:
  167. self.log_message(f"坐标 ({x}, {y}) 已存在,跳过重复更新")
  168. else:
  169. self.log_message("未找到有效的采集坐标")
  170. def perform_actions(self):
  171. """执行主要操作"""
  172. self.log_message("开始执行操作序列...")
  173. try:
  174. # 1. 右键点击指定位置
  175. pyautogui.click(1730, 300, button='right')
  176. self.log_message("已右键点击 (1730, 300)")
  177. time.sleep(0.5)
  178. # 2. 按键 A
  179. pyautogui.press('a')
  180. self.log_message("已按键 A")
  181. time.sleep(0.5)
  182. # 3. 按键 Ctrl+C
  183. pyautogui.hotkey('ctrl', 'c')
  184. self.log_message("已执行 Ctrl+C")
  185. time.sleep(0.5)
  186. # 4. 获取剪贴板内容
  187. clipboard_content = pyperclip.paste()
  188. if clipboard_content:
  189. self.log_message("成功获取剪贴板内容")
  190. self.parse_clipboard_content(clipboard_content)
  191. else:
  192. self.log_message("剪贴板内容为空")
  193. except Exception as e:
  194. self.log_message(f"操作执行失败: {str(e)}")
  195. def worker(self):
  196. """工作线程函数"""
  197. self.log_message("程序已启动,每10秒执行一次操作")
  198. while not self.stop_event.is_set():
  199. if not self.is_running:
  200. break
  201. self.perform_actions()
  202. # 等待10秒,但每秒检查一次停止信号
  203. for _ in range(10):
  204. if self.stop_event.is_set() or not self.is_running:
  205. break
  206. time.sleep(1)
  207. self.log_message("操作线程已停止")
  208. def start_action(self):
  209. """启动按钮回调"""
  210. if self.is_running:
  211. self.log_message("程序已在运行中")
  212. return
  213. # 清空上次的坐标记录
  214. self.last_coords = []
  215. self.stop_event.clear()
  216. self.is_running = True
  217. self.start_btn.config(state=tk.DISABLED)
  218. self.stop_btn.config(state=tk.NORMAL)
  219. self.thread = threading.Thread(target=self.worker, daemon=True)
  220. self.thread.start()
  221. def stop_action(self):
  222. """停止按钮回调"""
  223. if not self.is_running:
  224. return
  225. self.log_message("正在停止程序...")
  226. self.is_running = False
  227. self.stop_event.set()
  228. self.start_btn.config(state=tk.NORMAL)
  229. self.stop_btn.config(state=tk.DISABLED)
  230. def main():
  231. root = tk.Tk()
  232. app = AutoClickerApp(root)
  233. root.mainloop()
  234. if __name__ == "__main__":
  235. main()