6ed762f7 by 柴进

客户唤醒营销工具迭代,不再进行频繁的浏览器关闭

1 parent 9d72c970
...@@ -30,16 +30,34 @@ from selenium.common.exceptions import TimeoutException, NoSuchElementException ...@@ -30,16 +30,34 @@ from selenium.common.exceptions import TimeoutException, NoSuchElementException
30 30
31 31
32 class ChromeController: 32 class ChromeController:
33 """Chrome浏览器控制器""" 33 """Chrome浏览器控制器 - 单例模式,全局共享浏览器实例"""
34
35 _instance = None # 单例实例
36
37 def __new__(cls):
38 """单例模式: 确保全局只有一个浏览器实例"""
39 if cls._instance is None:
40 cls._instance = super().__new__(cls)
41 return cls._instance
34 42
35 def __init__(self): 43 def __init__(self):
44 # 防止重复初始化
45 if hasattr(self, '_initialized'):
46 return
47
36 self.driver = None 48 self.driver = None
37 self.wait = None 49 self.wait = None
38 self.network_logs = [] 50 self.network_logs = []
39 self.is_running = False 51 self.is_running = False
52 self._initialized = True
40 53
41 def start_browser(self) -> bool: 54 def start_browser(self) -> bool:
42 """启动Chrome浏览器""" 55 """启动Chrome浏览器 - 如果已启动则跳过"""
56 # 如果浏览器已经运行,直接返回成功
57 if self.is_running and self.driver:
58 print("Chrome浏览器已在运行,复用现有实例")
59 return True
60
43 try: 61 try:
44 if USING_UNDETECTED: 62 if USING_UNDETECTED:
45 # 使用undetected-chromedriver(推荐) 63 # 使用undetected-chromedriver(推荐)
...@@ -84,15 +102,23 @@ class ChromeController: ...@@ -84,15 +102,23 @@ class ChromeController:
84 return False 102 return False
85 103
86 def stop_browser(self): 104 def stop_browser(self):
87 """关闭浏览器""" 105 """关闭浏览器 - 仅在程序退出时调用"""
88 try: 106 try:
89 if self.driver: 107 if self.driver:
90 self.driver.quit() 108 self.driver.quit()
109 self.driver = None
91 self.is_running = False 110 self.is_running = False
92 print("Chrome浏览器已关闭") 111 print("Chrome浏览器已关闭")
93 except Exception as e: 112 except Exception as e:
94 print(f"关闭浏览器异常: {e}") 113 print(f"关闭浏览器异常: {e}")
95 114
115 def ensure_browser_running(self) -> bool:
116 """确保浏览器正在运行 - 供外部调用"""
117 if not self.is_running or not self.driver:
118 print("检测到浏览器未运行,正在启动...")
119 return self.start_browser()
120 return True
121
96 def navigate_to(self, url: str) -> bool: 122 def navigate_to(self, url: str) -> bool:
97 """导航到指定URL""" 123 """导航到指定URL"""
98 try: 124 try:
......
...@@ -46,7 +46,8 @@ class EtsyManager: ...@@ -46,7 +46,8 @@ class EtsyManager:
46 } 46 }
47 47
48 try: 48 try:
49 if not self.chrome.start_browser(): 49 # 确保浏览器运行
50 if not self.chrome.ensure_browser_running():
50 return result 51 return result
51 52
52 # 导航到消息页面 53 # 导航到消息页面
...@@ -83,15 +84,14 @@ class EtsyManager: ...@@ -83,15 +84,14 @@ class EtsyManager:
83 84
84 except Exception as e: 85 except Exception as e:
85 print(f"登录状态检查异常: {e}") 86 print(f"登录状态检查异常: {e}")
86 finally:
87 self.chrome.stop_browser()
88 87
89 return result 88 return result
90 89
91 def get_user_tags(self) -> Optional[Dict[str, int]]: 90 def get_user_tags(self) -> Optional[Dict[str, int]]:
92 """获取用户标签""" 91 """获取用户标签"""
93 try: 92 try:
94 if not self.chrome.start_browser(): 93 # 确保浏览器运行
94 if not self.chrome.ensure_browser_running():
95 return None 95 return None
96 96
97 if not self.chrome.navigate_to(self.PAGES["messages"]): 97 if not self.chrome.navigate_to(self.PAGES["messages"]):
...@@ -117,8 +117,6 @@ class EtsyManager: ...@@ -117,8 +117,6 @@ class EtsyManager:
117 117
118 except Exception as e: 118 except Exception as e:
119 print(f"获取用户标签异常: {e}") 119 print(f"获取用户标签异常: {e}")
120 finally:
121 self.chrome.stop_browser()
122 120
123 return None 121 return None
124 122
...@@ -130,7 +128,8 @@ class EtsyManager: ...@@ -130,7 +128,8 @@ class EtsyManager:
130 daily_limit = self.config.get("limits.daily_limit", 100) 128 daily_limit = self.config.get("limits.daily_limit", 100)
131 129
132 try: 130 try:
133 if not self.chrome.start_browser(): 131 # 确保浏览器运行
132 if not self.chrome.ensure_browser_running():
134 status_callback("浏览器启动失败") 133 status_callback("浏览器启动失败")
135 return 134 return
136 135
...@@ -175,7 +174,6 @@ class EtsyManager: ...@@ -175,7 +174,6 @@ class EtsyManager:
175 except Exception as e: 174 except Exception as e:
176 status_callback(f"对话营销异常: {e}") 175 status_callback(f"对话营销异常: {e}")
177 finally: 176 finally:
178 self.chrome.stop_browser()
179 self.is_marketing_active = False 177 self.is_marketing_active = False
180 178
181 def start_order_marketing(self, start_date: str, end_date: str, 179 def start_order_marketing(self, start_date: str, end_date: str,
...@@ -185,7 +183,8 @@ class EtsyManager: ...@@ -185,7 +183,8 @@ class EtsyManager:
185 sent_count = 0 183 sent_count = 0
186 184
187 try: 185 try:
188 if not self.chrome.start_browser(): 186 # 确保浏览器运行
187 if not self.chrome.ensure_browser_running():
189 status_callback("浏览器启动失败") 188 status_callback("浏览器启动失败")
190 return 189 return
191 190
...@@ -223,7 +222,6 @@ class EtsyManager: ...@@ -223,7 +222,6 @@ class EtsyManager:
223 except Exception as e: 222 except Exception as e:
224 status_callback(f"订单营销异常: {e}") 223 status_callback(f"订单营销异常: {e}")
225 finally: 224 finally:
226 self.chrome.stop_browser()
227 self.is_marketing_active = False 225 self.is_marketing_active = False
228 226
229 def stop_marketing(self): 227 def stop_marketing(self):
......
...@@ -29,6 +29,21 @@ class MainWindow: ...@@ -29,6 +29,21 @@ class MainWindow:
29 self.create_widgets() 29 self.create_widgets()
30 self.load_config_data() 30 self.load_config_data()
31 31
32 # 绑定窗口关闭事件
33 self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
34
35 def on_closing(self):
36 """窗口关闭事件处理"""
37 from ..etsy.chrome_controller import ChromeController
38
39 # 停止浏览器
40 chrome = ChromeController()
41 if chrome.is_running:
42 chrome.stop_browser()
43
44 # 关闭窗口
45 self.root.destroy()
46
32 def setup_window(self): 47 def setup_window(self):
33 """设置窗口属性""" 48 """设置窗口属性"""
34 self.root.title("Etsy客户营销工具 v1.0") 49 self.root.title("Etsy客户营销工具 v1.0")
......