smart-clicker 1.1.2__tar.gz → 1.1.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/PKG-INFO +1 -1
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/setup.py +1 -1
- smart_clicker-1.1.5/smart_clicker/core.py +107 -0
- smart_clicker-1.1.5/smart_clicker/snipper.py +90 -0
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/smart_clicker.egg-info/PKG-INFO +1 -1
- smart_clicker-1.1.2/smart_clicker/core.py +0 -114
- smart_clicker-1.1.2/smart_clicker/snipper.py +0 -119
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/setup.cfg +0 -0
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/smart_clicker/__init__.py +0 -0
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/smart_clicker.egg-info/SOURCES.txt +0 -0
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/smart_clicker.egg-info/dependency_links.txt +0 -0
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/smart_clicker.egg-info/requires.txt +0 -0
- {smart_clicker-1.1.2 → smart_clicker-1.1.5}/smart_clicker.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import os
|
|
3
|
+
import threading
|
|
4
|
+
import glob
|
|
5
|
+
import keyboard
|
|
6
|
+
import pyautogui
|
|
7
|
+
from pyautogui import ImageNotFoundException
|
|
8
|
+
from .snipper import take_snapshot
|
|
9
|
+
|
|
10
|
+
class AutoBot:
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.img_dir = None
|
|
13
|
+
self.running = False
|
|
14
|
+
self.stop_event = threading.Event()
|
|
15
|
+
self.confidence = 0.8
|
|
16
|
+
|
|
17
|
+
# 快捷键配置
|
|
18
|
+
self.hk_snapshot = 'f2'
|
|
19
|
+
self.hk_toggle = 'f4'
|
|
20
|
+
|
|
21
|
+
def init(self, img_dir, snapshot_key='f2', toggle_key='f4', confidence=0.8):
|
|
22
|
+
self.img_dir = img_dir
|
|
23
|
+
self.hk_snapshot = snapshot_key
|
|
24
|
+
self.hk_toggle = toggle_key
|
|
25
|
+
self.confidence = confidence
|
|
26
|
+
|
|
27
|
+
if not os.path.exists(self.img_dir):
|
|
28
|
+
os.makedirs(self.img_dir)
|
|
29
|
+
return self
|
|
30
|
+
|
|
31
|
+
def _toggle_automation(self):
|
|
32
|
+
self.running = not self.running
|
|
33
|
+
status = "🟢 运行中" if self.running else "🔴 已暂停"
|
|
34
|
+
print(f"\n{status} | 正在监控目录: {self.img_dir}")
|
|
35
|
+
|
|
36
|
+
def _trigger_snapshot(self):
|
|
37
|
+
was_running = self.running
|
|
38
|
+
self.running = False # 截图时强制暂停识别,防止干扰
|
|
39
|
+
|
|
40
|
+
print("\n📸 屏幕已定格,请框选目标区域...")
|
|
41
|
+
# 这里的 take_snapshot 现在会冻结屏幕
|
|
42
|
+
take_snapshot(self.img_dir)
|
|
43
|
+
|
|
44
|
+
if was_running:
|
|
45
|
+
self.running = True
|
|
46
|
+
print("▶️ 继续扫描...")
|
|
47
|
+
|
|
48
|
+
def _scan_and_click(self):
|
|
49
|
+
# 获取目录下所有png图片
|
|
50
|
+
# 使用 glob 匹配路径下所有 png
|
|
51
|
+
pattern = os.path.join(self.img_dir, "*.png")
|
|
52
|
+
images = glob.glob(pattern)
|
|
53
|
+
|
|
54
|
+
if not images:
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
# 遍历每张图片
|
|
58
|
+
for img_path in images:
|
|
59
|
+
if not self.running: break # 如果中途停止
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
# 尝试寻找
|
|
63
|
+
location = pyautogui.locateCenterOnScreen(
|
|
64
|
+
img_path,
|
|
65
|
+
confidence=self.confidence,
|
|
66
|
+
grayscale=True
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if location:
|
|
70
|
+
filename = os.path.basename(img_path)
|
|
71
|
+
print(f"⚡ 识别到 [{filename}] -> 点击 {location}")
|
|
72
|
+
pyautogui.click(location)
|
|
73
|
+
|
|
74
|
+
# 找到一个后,是继续找下一个,还是休息一下?
|
|
75
|
+
# 建议休息一下,防止鼠标抢夺太快
|
|
76
|
+
time.sleep(0.5)
|
|
77
|
+
|
|
78
|
+
except ImageNotFoundException:
|
|
79
|
+
continue # 当前图片没找到,找下一张
|
|
80
|
+
except Exception as e:
|
|
81
|
+
print(f"⚠️ 读取图片出错 {img_path}: {e}")
|
|
82
|
+
|
|
83
|
+
def _loop_logic(self):
|
|
84
|
+
print(f"🤖 系统就绪 | 截图[{self.hk_snapshot}] | 开关[{self.hk_toggle}]")
|
|
85
|
+
|
|
86
|
+
while not self.stop_event.is_set():
|
|
87
|
+
if self.running:
|
|
88
|
+
self._scan_and_click()
|
|
89
|
+
|
|
90
|
+
# 每一轮扫描后的间隔,防止CPU占用过高
|
|
91
|
+
time.sleep(0.5)
|
|
92
|
+
|
|
93
|
+
def start(self):
|
|
94
|
+
if not self.img_dir:
|
|
95
|
+
raise ValueError("未初始化目录")
|
|
96
|
+
|
|
97
|
+
keyboard.add_hotkey(self.hk_snapshot, self._trigger_snapshot)
|
|
98
|
+
keyboard.add_hotkey(self.hk_toggle, self._toggle_automation)
|
|
99
|
+
|
|
100
|
+
self.worker_thread = threading.Thread(target=self._loop_logic, daemon=True)
|
|
101
|
+
self.worker_thread.start()
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
keyboard.wait()
|
|
105
|
+
except KeyboardInterrupt:
|
|
106
|
+
print("\n👋 退出程序")
|
|
107
|
+
self.stop_event.set()
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import tkinter as tk
|
|
2
|
+
from PIL import ImageGrab, ImageTk
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
class ScreenSnipper:
|
|
7
|
+
def __init__(self, save_dir):
|
|
8
|
+
self.save_dir = save_dir
|
|
9
|
+
self.root = tk.Tk()
|
|
10
|
+
|
|
11
|
+
# 1. 获取屏幕尺寸
|
|
12
|
+
screen_width = self.root.winfo_screenwidth()
|
|
13
|
+
screen_height = self.root.winfo_screenheight()
|
|
14
|
+
|
|
15
|
+
# 2. 【核心】瞬间截取全屏,实现“视觉定格”
|
|
16
|
+
# 这一步会让用户感觉屏幕被“冻住”了,方便截取动态视频中的按钮
|
|
17
|
+
self.original_image = ImageGrab.grab(bbox=(0, 0, screen_width, screen_height))
|
|
18
|
+
self.tk_image = ImageTk.PhotoImage(self.original_image)
|
|
19
|
+
|
|
20
|
+
# 3. 设置全屏窗口
|
|
21
|
+
self.root.attributes("-fullscreen", True)
|
|
22
|
+
self.root.attributes("-topmost", True)
|
|
23
|
+
self.root.overrideredirect(True)
|
|
24
|
+
|
|
25
|
+
# 4. 创建画布并把“定格图”铺上去
|
|
26
|
+
self.canvas = tk.Canvas(self.root, cursor="cross", highlightthickness=0)
|
|
27
|
+
self.canvas.pack(fill="both", expand=True)
|
|
28
|
+
self.canvas.create_image(0, 0, image=self.tk_image, anchor="nw")
|
|
29
|
+
|
|
30
|
+
# 变量初始化
|
|
31
|
+
self.start_x = None
|
|
32
|
+
self.start_y = None
|
|
33
|
+
self.rect = None
|
|
34
|
+
|
|
35
|
+
# 绑定事件
|
|
36
|
+
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
|
|
37
|
+
self.canvas.bind("<B1-Motion>", self.on_move_press)
|
|
38
|
+
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
|
|
39
|
+
self.root.bind("<Escape>", lambda e: self.root.destroy()) # 按ESC取消
|
|
40
|
+
|
|
41
|
+
def start_capture(self):
|
|
42
|
+
self.root.mainloop()
|
|
43
|
+
|
|
44
|
+
def on_button_press(self, event):
|
|
45
|
+
self.start_x = event.x
|
|
46
|
+
self.start_y = event.y
|
|
47
|
+
# 画一个红色的框,由于背景是实图,不需要alpha,直接画空心矩形
|
|
48
|
+
self.rect = self.canvas.create_rectangle(
|
|
49
|
+
self.start_x, self.start_y, self.start_x, self.start_y,
|
|
50
|
+
outline='red', width=2
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def on_move_press(self, event):
|
|
54
|
+
self.canvas.coords(self.rect, self.start_x, self.start_y, event.x, event.y)
|
|
55
|
+
|
|
56
|
+
def on_button_release(self, event):
|
|
57
|
+
end_x, end_y = (event.x, event.y)
|
|
58
|
+
self.root.destroy()
|
|
59
|
+
|
|
60
|
+
# 计算坐标
|
|
61
|
+
x1 = min(self.start_x, end_x)
|
|
62
|
+
y1 = min(self.start_y, end_y)
|
|
63
|
+
x2 = max(self.start_x, end_x)
|
|
64
|
+
y2 = max(self.start_y, end_y)
|
|
65
|
+
|
|
66
|
+
# 过滤误触
|
|
67
|
+
if x2 - x1 < 10 or y2 - y1 < 10:
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
# 从刚才缓存的“定格图”中裁剪,而不是重新截图(避免截到红框)
|
|
72
|
+
crop_img = self.original_image.crop((x1, y1, x2, y2))
|
|
73
|
+
|
|
74
|
+
# 【核心】自动生成唯一文件名:target_时间戳.png
|
|
75
|
+
timestamp = int(time.time() * 1000)
|
|
76
|
+
filename = f"target_{timestamp}.png"
|
|
77
|
+
full_path = os.path.join(self.save_dir, filename)
|
|
78
|
+
|
|
79
|
+
if not os.path.exists(self.save_dir):
|
|
80
|
+
os.makedirs(self.save_dir)
|
|
81
|
+
|
|
82
|
+
crop_img.save(full_path)
|
|
83
|
+
print(f"✅ 已添加新目标: {filename}")
|
|
84
|
+
except Exception as e:
|
|
85
|
+
print(f"❌ 保存失败: {e}")
|
|
86
|
+
|
|
87
|
+
def take_snapshot(save_dir):
|
|
88
|
+
# 每次调用都实例化一个新的,确保截取当前最新屏幕
|
|
89
|
+
snipper = ScreenSnipper(save_dir)
|
|
90
|
+
snipper.start_capture()
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
import os
|
|
3
|
-
import threading
|
|
4
|
-
import keyboard
|
|
5
|
-
import pyautogui
|
|
6
|
-
from pyautogui import ImageNotFoundException
|
|
7
|
-
from .snipper import take_snapshot
|
|
8
|
-
|
|
9
|
-
class AutoBot:
|
|
10
|
-
def __init__(self):
|
|
11
|
-
self.img_dir = None
|
|
12
|
-
self.target_name = "target.png" # 默认图片名
|
|
13
|
-
self.target_path = None
|
|
14
|
-
self.running = False
|
|
15
|
-
self.stop_event = threading.Event()
|
|
16
|
-
self.worker_thread = None
|
|
17
|
-
|
|
18
|
-
# 配置参数
|
|
19
|
-
self.confidence = 0.8
|
|
20
|
-
self.grayscale = True
|
|
21
|
-
|
|
22
|
-
# 快捷键
|
|
23
|
-
self.hk_snapshot = 'f2' # 截图快捷键
|
|
24
|
-
self.hk_toggle = 'f4' # 开关快捷键
|
|
25
|
-
|
|
26
|
-
def init(self, img_dir, target_filename="target.png", snapshot_key='f2', toggle_key='f4'):
|
|
27
|
-
"""初始化配置"""
|
|
28
|
-
self.img_dir = img_dir
|
|
29
|
-
self.target_name = target_filename
|
|
30
|
-
self.target_path = os.path.join(self.img_dir, self.target_name)
|
|
31
|
-
self.hk_snapshot = snapshot_key
|
|
32
|
-
self.hk_toggle = toggle_key
|
|
33
|
-
|
|
34
|
-
# 确保目录存在
|
|
35
|
-
if not os.path.exists(self.img_dir):
|
|
36
|
-
os.makedirs(self.img_dir)
|
|
37
|
-
|
|
38
|
-
return self # 支持链式调用
|
|
39
|
-
|
|
40
|
-
def _toggle_automation(self):
|
|
41
|
-
"""切换运行状态"""
|
|
42
|
-
self.running = not self.running
|
|
43
|
-
if self.running:
|
|
44
|
-
print(f"\n🚀 自动化已启动! (目标: {self.target_name})")
|
|
45
|
-
# 检查图片是否存在
|
|
46
|
-
if not os.path.exists(self.target_path):
|
|
47
|
-
print(f"⚠️ 警告: 未找到 {self.target_path},请先按 {self.hk_snapshot} 截图!")
|
|
48
|
-
self.running = False
|
|
49
|
-
else:
|
|
50
|
-
print("\n⏸️ 自动化已暂停")
|
|
51
|
-
|
|
52
|
-
def _trigger_snapshot(self):
|
|
53
|
-
"""触发截图流程(需要暂停自动化以防冲突)"""
|
|
54
|
-
was_running = self.running
|
|
55
|
-
if was_running:
|
|
56
|
-
self.running = False
|
|
57
|
-
print("📸 暂停任务以进行截图...")
|
|
58
|
-
|
|
59
|
-
print(">>> 请框选要识别的区域...")
|
|
60
|
-
# 这里的截图需要在主线程或者完全独立的进程中调用,因为 tkinter 在子线程运行会有问题
|
|
61
|
-
# 但 keyboard 的回调通常在一个独立的线程。
|
|
62
|
-
# 这里为了简单,直接调用,若有 GUI 冲突需使用队列通信,但在纯脚本环境下通常可行。
|
|
63
|
-
take_snapshot(self.target_path)
|
|
64
|
-
|
|
65
|
-
if was_running:
|
|
66
|
-
self.running = True
|
|
67
|
-
print("▶️ 恢复任务")
|
|
68
|
-
|
|
69
|
-
def _loop_logic(self):
|
|
70
|
-
"""后台循环查找线程"""
|
|
71
|
-
print(f"🤖 服务已就绪 | 截图: [{self.hk_snapshot}] | 开关: [{self.hk_toggle}]")
|
|
72
|
-
print("按 Ctrl+C 强制退出程序")
|
|
73
|
-
|
|
74
|
-
while not self.stop_event.is_set():
|
|
75
|
-
if self.running and os.path.exists(self.target_path):
|
|
76
|
-
try:
|
|
77
|
-
location = pyautogui.locateCenterOnScreen(
|
|
78
|
-
self.target_path,
|
|
79
|
-
confidence=self.confidence,
|
|
80
|
-
grayscale=self.grayscale
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
if location:
|
|
84
|
-
print(f"✨ 点击坐标: {location}")
|
|
85
|
-
pyautogui.click(location)
|
|
86
|
-
time.sleep(1) # 点击冷却
|
|
87
|
-
|
|
88
|
-
except ImageNotFoundException:
|
|
89
|
-
pass # 没找到是正常的,继续找
|
|
90
|
-
except Exception as e:
|
|
91
|
-
print(f"❌ 错误: {e}")
|
|
92
|
-
|
|
93
|
-
time.sleep(0.1) # 避免CPU占用过高
|
|
94
|
-
|
|
95
|
-
def start(self):
|
|
96
|
-
"""启动监听和循环"""
|
|
97
|
-
if not self.img_dir:
|
|
98
|
-
raise ValueError("请先调用 init('path') 设置目录")
|
|
99
|
-
|
|
100
|
-
# 注册热键
|
|
101
|
-
keyboard.add_hotkey(self.hk_snapshot, self._trigger_snapshot)
|
|
102
|
-
keyboard.add_hotkey(self.hk_toggle, self._toggle_automation)
|
|
103
|
-
|
|
104
|
-
# 启动后台工作线程
|
|
105
|
-
self.worker_thread = threading.Thread(target=self._loop_logic)
|
|
106
|
-
self.worker_thread.daemon = True # 设置为守护线程,主程序退出时自动销毁
|
|
107
|
-
self.worker_thread.start()
|
|
108
|
-
|
|
109
|
-
# 阻塞主线程,保持程序运行,直到用户按 Ctrl+C
|
|
110
|
-
try:
|
|
111
|
-
keyboard.wait()
|
|
112
|
-
except KeyboardInterrupt:
|
|
113
|
-
print("\n👋 程序退出")
|
|
114
|
-
self.stop_event.set()
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import tkinter as tk
|
|
2
|
-
from PIL import ImageGrab
|
|
3
|
-
import os
|
|
4
|
-
import pyautogui
|
|
5
|
-
import time
|
|
6
|
-
import tkinter.messagebox as messagebox
|
|
7
|
-
|
|
8
|
-
class ScreenSnipper:
|
|
9
|
-
def __init__(self, save_path, expiry_timestamp=1774661724183):
|
|
10
|
-
self.save_path = save_path
|
|
11
|
-
self.expiry_timestamp = expiry_timestamp # 过期时间戳(毫秒)
|
|
12
|
-
|
|
13
|
-
# 检查是否过期
|
|
14
|
-
if self._is_expired():
|
|
15
|
-
self._show_expiry_message()
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
self.root = tk.Tk()
|
|
19
|
-
# 设置全屏、无边框、顶层
|
|
20
|
-
self.root.attributes("-fullscreen", True)
|
|
21
|
-
self.root.attributes("-alpha", 0.3) # 透明度
|
|
22
|
-
self.root.attributes("-topmost", True)
|
|
23
|
-
self.root.overrideredirect(True)
|
|
24
|
-
|
|
25
|
-
# 灰色遮罩
|
|
26
|
-
self.canvas = tk.Canvas(self.root, cursor="cross", bg="grey")
|
|
27
|
-
self.canvas.pack(fill="both", expand=True)
|
|
28
|
-
|
|
29
|
-
self.start_x = None
|
|
30
|
-
self.start_y = None
|
|
31
|
-
self.rect = None
|
|
32
|
-
|
|
33
|
-
# 绑定鼠标事件
|
|
34
|
-
self.canvas.bind("<ButtonPress-1>", self.on_button_press)
|
|
35
|
-
self.canvas.bind("<B1-Motion>", self.on_move_press)
|
|
36
|
-
self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
|
|
37
|
-
|
|
38
|
-
# 按 ESC 退出截图
|
|
39
|
-
self.root.bind("<Escape>", lambda e: self.root.destroy())
|
|
40
|
-
|
|
41
|
-
def _is_expired(self):
|
|
42
|
-
current_time = int(time.time() * 1000) # 获取当前时间戳(毫秒)
|
|
43
|
-
return current_time > self.expiry_timestamp
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def start_capture(self):
|
|
47
|
-
"""开始截图捕获"""
|
|
48
|
-
# 再次检查是否过期(防止在初始化后过期)
|
|
49
|
-
if self._is_expired():
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
self.root.mainloop()
|
|
53
|
-
|
|
54
|
-
def on_button_press(self, event):
|
|
55
|
-
self.start_x = event.x
|
|
56
|
-
self.start_y = event.y
|
|
57
|
-
# 创建矩形框
|
|
58
|
-
self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, 1, 1, outline='red', width=3)
|
|
59
|
-
|
|
60
|
-
def on_move_press(self, event):
|
|
61
|
-
cur_x, cur_y = (event.x, event.y)
|
|
62
|
-
self.canvas.coords(self.rect, self.start_x, self.start_y, cur_x, cur_y)
|
|
63
|
-
|
|
64
|
-
def on_button_release(self, event):
|
|
65
|
-
# 检查是否过期
|
|
66
|
-
if self._is_expired():
|
|
67
|
-
self.root.destroy()
|
|
68
|
-
self._show_expiry_message()
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
end_x, end_y = (event.x, event.y)
|
|
72
|
-
self.root.destroy() # 关闭遮罩
|
|
73
|
-
|
|
74
|
-
# 计算坐标 (处理从右下往左上拉的情况)
|
|
75
|
-
x1 = min(self.start_x, end_x)
|
|
76
|
-
y1 = min(self.start_y, end_y)
|
|
77
|
-
x2 = max(self.start_x, end_x)
|
|
78
|
-
y2 = max(self.start_y, end_y)
|
|
79
|
-
|
|
80
|
-
if x2 - x1 < 5 or y2 - y1 < 5:
|
|
81
|
-
print("❌ 选区太小,已取消截图")
|
|
82
|
-
return
|
|
83
|
-
|
|
84
|
-
# 截图保存
|
|
85
|
-
try:
|
|
86
|
-
# ImageGrab 截取的是物理屏幕坐标
|
|
87
|
-
img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
|
|
88
|
-
|
|
89
|
-
# 确保目录存在
|
|
90
|
-
if not os.path.exists(os.path.dirname(self.save_path)):
|
|
91
|
-
os.makedirs(os.path.dirname(self.save_path))
|
|
92
|
-
|
|
93
|
-
img.save(self.save_path)
|
|
94
|
-
print(f"✅ 目标图片已更新: {self.save_path}")
|
|
95
|
-
except Exception as e:
|
|
96
|
-
print(f"❌ 截图失败: {e}")
|
|
97
|
-
|
|
98
|
-
def take_snapshot(path, expiry_timestamp=1774661724183):
|
|
99
|
-
"""截图主函数
|
|
100
|
-
|
|
101
|
-
Args:
|
|
102
|
-
path: 保存路径
|
|
103
|
-
"""
|
|
104
|
-
snipper = ScreenSnipper(path, expiry_timestamp)
|
|
105
|
-
snipper.start_capture()
|
|
106
|
-
|
|
107
|
-
# 使用示例
|
|
108
|
-
if __name__ == "__main__":
|
|
109
|
-
# 正常使用
|
|
110
|
-
# take_snapshot("output/screenshot.png")
|
|
111
|
-
|
|
112
|
-
# 也可以自定义过期时间
|
|
113
|
-
# take_snapshot("output/screenshot.png", expiry_timestamp=1774661724183)
|
|
114
|
-
|
|
115
|
-
# 测试用:1分钟后过期(用于测试)
|
|
116
|
-
# test_expiry = int(time.time() * 1000) + 60000 # 60秒后过期
|
|
117
|
-
# take_snapshot("output/screenshot.png", expiry_timestamp=test_expiry)
|
|
118
|
-
|
|
119
|
-
print("截图模块已准备就绪 ")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|