Files
proxy_cursor_regv206/cursor_pro_register.py
huangzhenpc 89c5fd4cf9 first commit
2025-03-11 15:52:54 +08:00

848 lines
31 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import platform
import json
import sys
from colorama import Fore, Style
from enum import Enum
from typing import Optional
from account_sync import AccountSync
os.environ["PYTHONVERBOSE"] = "0"
os.environ["PYINSTALLER_VERBOSE"] = "0"
import time
import random
import os
from logger import logging
from browser_utils import BrowserManager
from logo import print_logo
from datetime import datetime
import requests
# 定义 EMOJI 字典
EMOJI = {"ERROR": "", "WARNING": "⚠️", "INFO": ""}
class VerificationStatus(Enum):
"""验证状态枚举"""
PASSWORD_PAGE = "@name=password"
CAPTCHA_PAGE = "@data-index=0"
ACCOUNT_SETTINGS = "Account Settings"
class TurnstileError(Exception):
"""Turnstile 验证相关异常"""
pass
def save_screenshot(tab, stage: str, timestamp: bool = True) -> None:
"""
保存页面截图
Args:
tab: 浏览器标签页对象
stage: 截图阶段标识
timestamp: 是否添加时间戳
"""
try:
# 创建 screenshots 目录
screenshot_dir = "screenshots"
if not os.path.exists(screenshot_dir):
os.makedirs(screenshot_dir)
# 生成文件名
if timestamp:
filename = f"turnstile_{stage}_{int(time.time())}.png"
else:
filename = f"turnstile_{stage}.png"
filepath = os.path.join(screenshot_dir, filename)
# 保存截图
tab.get_screenshot(filepath)
logging.debug(f"截图已保存: {filepath}")
except Exception as e:
logging.warning(f"截图保存失败: {str(e)}")
def check_verification_success(tab) -> Optional[VerificationStatus]:
"""
检查验证是否成功
Returns:
VerificationStatus: 验证成功时返回对应状态,失败返回 None
"""
for status in VerificationStatus:
if tab.ele(status.value):
logging.info(f"验证成功 - 已到达{status.name}页面")
return status
return None
def handle_turnstile(tab, max_retries: int = 2, retry_interval: tuple = (1, 2), start_time=None) -> bool:
"""
处理 Turnstile 验证
Args:
tab: 浏览器标签页对象
max_retries: 最大重试次数
retry_interval: 重试间隔时间范围(最小值, 最大值)
start_time: 注册开始时间戳,用于超时检查
Returns:
bool: 验证是否成功
Raises:
TurnstileError: 验证过程中出现异常
"""
logging.info("正在检测 Turnstile 验证...")
# save_screenshot(tab, "start")
retry_count = 0
try:
while retry_count < max_retries:
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时放弃Turnstile验证")
return False
retry_count += 1
logging.debug(f"{retry_count} 次尝试验证")
try:
# 定位验证框元素
challenge_check = (
tab.ele("@id=cf-turnstile", timeout=2)
.child()
.shadow_root.ele("tag:iframe")
.ele("tag:body")
.sr("tag:input")
)
if challenge_check:
logging.info("检测到 Turnstile 验证框,开始处理...")
# 随机延时后点击验证
time.sleep(random.uniform(1, 3))
challenge_check.click()
time.sleep(2)
# 保存验证后的截图
# save_screenshot(tab, "clicked")
# 检查验证结果
if check_verification_success(tab):
logging.info("Turnstile 验证通过")
# save_screenshot(tab, "success")
return True
except Exception as e:
logging.debug(f"当前尝试未成功: {str(e)}")
# 检查是否已经验证成功
if check_verification_success(tab):
return True
# 随机延时后继续下一次尝试
time.sleep(random.uniform(*retry_interval))
# 超出最大重试次数
logging.error(f"验证失败 - 已达到最大重试次数 {max_retries}")
logging.error(
"请前往开源项目查看更多信息https://github.com/chengazhen/cursor-auto-free"
)
# save_screenshot(tab, "failed")
return False
except Exception as e:
error_msg = f"Turnstile 验证过程发生异常: {str(e)}"
logging.error(error_msg)
# save_screenshot(tab, "error")
raise TurnstileError(error_msg)
def get_cursor_session_token(tab, max_attempts=3, retry_interval=2, start_time=None):
"""
获取Cursor会话token带有重试机制
:param tab: 浏览器标签页
:param max_attempts: 最大尝试次数
:param retry_interval: 重试间隔(秒)
:param start_time: 注册开始时间戳,用于超时检查
:return: session token 或 None
"""
logging.info("开始获取cookie")
attempts = 0
while attempts < max_attempts:
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃获取会话令牌")
return None
try:
cookies = tab.cookies()
for cookie in cookies:
if cookie.get("name") == "WorkosCursorSessionToken":
return cookie["value"].split("%3A%3A")[1]
attempts += 1
if attempts < max_attempts:
logging.warning(
f"{attempts} 次尝试未获取到CursorSessionToken{retry_interval}秒后重试..."
)
time.sleep(retry_interval)
else:
logging.error(
f"已达到最大尝试次数({max_attempts})获取CursorSessionToken失败"
)
except Exception as e:
logging.error(f"获取cookie失败: {str(e)}")
attempts += 1
if attempts < max_attempts:
logging.info(f"将在 {retry_interval} 秒后重试...")
time.sleep(retry_interval)
return None
registration_timeout = 240 # 默认超时时间4分钟
def check_timeout(start_time, timeout=registration_timeout):
"""检查是否超时
Args:
start_time: 开始时间戳
timeout: 超时时间(秒)
Returns:
bool: 是否超时
"""
elapsed_time = time.time() - start_time
if elapsed_time > timeout:
logging.warning(f"⚠️ 注册超时!已经过去 {elapsed_time:.1f} 秒,超过设定的 {timeout} 秒限制")
return True
return False
def sign_up_account(browser, tab, start_time=None):
logging.info("=== 开始注册账号流程 ===")
logging.info(f"正在访问注册页面: {sign_up_url}")
tab.get(sign_up_url)
try:
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
if tab.ele("@name=first_name"):
logging.info("正在填写个人信息...")
tab.actions.click("@name=first_name").input(first_name)
logging.info(f"已输入名字: {first_name}")
time.sleep(random.uniform(1, 3))
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
tab.actions.click("@name=last_name").input(last_name)
logging.info(f"已输入姓氏: {last_name}")
time.sleep(random.uniform(1, 3))
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
tab.actions.click("@name=email").input(account)
logging.info(f"已输入邮箱: {account}")
time.sleep(random.uniform(1, 3))
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
logging.info("提交个人信息...")
tab.actions.click("@type=submit")
except Exception as e:
logging.error(f"注册页面访问失败: {str(e)}")
return False
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
# 进行第一次Turnstile验证如果失败则返回False
if not handle_turnstile(tab, start_time=start_time):
logging.error("第一次Turnstile验证失败停止当前注册流程")
return False
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
try:
if tab.ele("@name=password"):
logging.info("正在设置密码...")
tab.ele("@name=password").input(password)
time.sleep(random.uniform(1, 3))
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
logging.info("提交密码...")
tab.ele("@type=submit").click()
logging.info("密码设置完成,等待系统响应...")
except Exception as e:
logging.error(f"密码设置失败: {str(e)}")
return False
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
if tab.ele("This email is not available."):
logging.error("注册失败:邮箱已被使用")
return False
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
# 进行第二次Turnstile验证如果失败则返回False
if not handle_turnstile(tab, start_time=start_time):
logging.error("第二次Turnstile验证失败停止当前注册流程")
return False
# 检查是否超时
if start_time and check_timeout(start_time):
logging.warning("注册超时,放弃当前注册流程")
return False
while True:
try:
if tab.ele("Account Settings"):
logging.info("注册成功 - 已进入账户设置页面")
break
if tab.ele("@data-index=0"):
logging.info("正在获取邮箱验证码...")
response = requests.get('https://rnemail.nosqli.com/latest_email?recipient=' + account)
if response.status_code == 200:
email_data = response.json()
code = email_data.get('code')
if not code:
logging.error("获取验证码失败")
return False
logging.info(f"成功获取验证码: {code}")
logging.info("正在输入验证码...")
i = 0
for digit in code:
tab.ele(f"@data-index={i}").input(digit)
time.sleep(random.uniform(0.1, 0.3))
i += 1
logging.info("验证码输入完成")
break
else:
logging.error("获取验证码请求失败")
return False
break
except Exception as e:
logging.error(f"验证码处理过程出错: {str(e)}")
return False
# 进行第三次Turnstile验证如果失败则返回False
if not handle_turnstile(tab):
logging.error("第三次Turnstile验证失败但继续执行后续流程")
# 这里我们选择继续执行,因为此时可能已经成功注册
wait_time = random.randint(3, 6)
for i in range(wait_time):
logging.info(f"等待系统处理中... 剩余 {wait_time-i}")
time.sleep(1)
logging.info("正在获取账户信息...")
tab.get(settings_url)
try:
usage_selector = (
"css:div.col-span-2 > div > div > div > div > "
"div:nth-child(1) > div.flex.items-center.justify-between.gap-2 > "
"span.font-mono.text-sm\\/\\[0\\.875rem\\]"
)
usage_ele = tab.ele(usage_selector)
if usage_ele:
usage_info = usage_ele.text
total_usage = usage_info.split("/")[-1].strip()
logging.info(f"账户可用额度上限: {total_usage}")
logging.info(
"请使用听泉助手https://cursorapi.nosqli.com/upload/听泉cursor助手v3.5.3.zip "
)
except Exception as e:
logging.error(f"获取账户额度信息失败: {str(e)}")
logging.info("\n=== 注册完成 ===")
account_info = f"Cursor 账号信息:\n邮箱: {account}\n密码: {password}"
logging.info(account_info)
time.sleep(5)
return True
def get_allowed_domains(max_attempts=3, retry_interval=2):
"""获取当前允许的域名列表"""
attempts = 0
while attempts < max_attempts:
try:
response = requests.get('https://rnemail.nosqli.com/allowed_domains/list')
if response.status_code == 200:
# 解析字符串格式的 JSON
return json.loads(response.text) # 使用 json.loads 解析
else:
logging.error(f"获取域名列表失败: {response.status_code}")
return []
except Exception as e:
logging.error(f"请求域名列表时发生错误: {str(e)}")
attempts += 1
if attempts < max_attempts:
logging.info(f"将在 {retry_interval} 秒后重试...")
time.sleep(retry_interval)
return [] # 返回空列表
class EmailGenerator:
def __init__(self,
password="".join(
random.choices(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*",
k=12,
)
),
selected_domain=None,
):
if not selected_domain:
logging.error("没有可用的域名,无法生成邮箱")
raise ValueError("没有可用的域名") # 抛出异常
self.selected_domain = selected_domain # 直接使用传入的域名
self.default_password = password
self.default_first_name = self.generate_random_name()
self.default_last_name = self.generate_random_name()
def generate_random_name(self, length=6):
"""生成随机用户名"""
first_letter = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
rest_letters = "".join(
random.choices("abcdefghijklmnopqrstuvwxyz", k=length - 1)
)
return first_letter + rest_letters
def generate_email(self):
"""生成随机邮箱地址"""
# 使用用户的名字和姓氏的首字母生成邮箱前缀
email_prefix = f"{self.default_first_name[0].lower()}{self.default_last_name.lower()}"
# 添加简短的随机数字以增加唯一性
random_suffix = "".join(random.choices("0123456789", k=2)) # 生成2位随机数字
return f"{email_prefix}{random_suffix}@{self.selected_domain}" # 使用选定的域名
def get_account_info(self):
"""获取完整的账号信息"""
return {
"email": self.generate_email(),
"password": self.default_password,
"first_name": self.default_first_name,
"last_name": self.default_last_name,
}
def get_user_agent(proxy_choice=None, custom_api=None):
"""获取user_agent
Args:
proxy_choice: 代理选择 (1=本地代理, 2=全局代理)
custom_api: 自定义代理API地址
"""
browser_manager = None
try:
# 使用JavaScript获取user agent
logging.info("初始化临时浏览器以获取User-Agent...")
browser_manager = BrowserManager()
browser, proxy_info = browser_manager.init_browser(
proxy_choice=proxy_choice,
custom_api=custom_api
)
user_agent = browser.latest_tab.run_js("return navigator.userAgent")
logging.info(f"获取到User-Agent: {user_agent}")
proxy_host, proxy_port, proxy_username, proxy_password = proxy_info
logging.info(f"初始化proxy: {proxy_host}:{proxy_port}")
return user_agent
except Exception as e:
logging.error(f"获取user agent失败: {str(e)}")
return None
finally:
# 确保浏览器实例被正确关闭
if browser_manager:
logging.info("关闭临时浏览器...")
browser_manager.quit()
def print_end_message():
logging.info("\n\n\n\n\n")
logging.info("=" * 30)
logging.info("所有操作已完成")
logging.info("\n=== 获取更多信息 ===")
logging.info("🔥 vx: behikcigar")
logging.info("=" * 30)
logging.info(
"请使用听泉助手https://cursorapi.nosqli.com/upload/听泉cursor助手v3.5.3.zip "
)
if __name__ == "__main__":
print_logo()
browser_manager = None
try:
logging.info("\n=== 初始化程序 ===")
# 选择账号同步API
print("\n请选择账号同步API:")
print("1. 听泉助手池")
print("2. 高质量号池")
while True:
try:
sync_api_choice = int(input("请输入选项 (1 或 2): ").strip())
if sync_api_choice in [1, 2]:
break
else:
print("无效的选项,请重新输入")
except ValueError:
print("请输入有效的数字")
# 根据选择创建AccountSync实例
account_sync = AccountSync(api_choice=sync_api_choice)
# 选择代理模式
print("\n请选择代理模式:")
print("1. 本地代理")
print("2. 全局代理")
print("3. 自定义代理API")
while True:
try:
proxy_choice = int(input("请输入选项 (1、2 或 3): ").strip())
if proxy_choice in [1, 2, 3]:
break
else:
print("无效的选项,请重新输入")
except ValueError:
print("请输入有效的数字")
# 如果选择自定义API获取API地址
custom_api = None
if proxy_choice == 3:
custom_api = input("请输入自定义代理API地址: ").strip()
if not custom_api:
print("API地址不能为空将使用默认全局代理")
proxy_choice = 2
# 将代理选择保存为全局变量,供后续使用
global_proxy_choice = proxy_choice
global_custom_api = custom_api
# 提示用户选择操作模式
print("\n请选择操作模式:")
print("1. 仅重置机器码")
print("2. 单个注册流程")
print("3. 批量注册流程")
while True:
try:
choice = int(input("请输入选项 (1、2 或 3): ").strip())
if choice in [1, 2, 3]:
break
else:
print("无效的选项,请重新输入")
except ValueError:
print("请输入有效的数字")
if choice == 1:
# 仅执行重置机器码
logging.info("机器码重置完成")
print_end_message()
sys.exit(0)
# 获取注册数量
register_count = 1
if choice == 3:
while True:
try:
register_count = int(input("请输入要注册的账号数量: ").strip())
if register_count > 0:
break
else:
print("请输入大于0的数字")
except ValueError:
print("请输入有效的数字")
logging.info("正在初始化浏览器...")
# 获取user_agent传递代理选择参数
user_agent = get_user_agent(proxy_choice=global_proxy_choice, custom_api=global_custom_api)
if not user_agent:
logging.error("获取user agent失败使用默认值")
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
# 剔除user_agent中的"HeadlessChrome"
user_agent = user_agent.replace("HeadlessChrome", "Chrome")
# 获取并打印浏览器的user-agent
# user_agent = browser.latest_tab.run_js("return navigator.userAgent")
logging.info("正在初始化邮箱验证模块...")
email_handler = None # 先初始化为None,后面根据配置创建
logging.info("\n=== 配置信息 ===")
login_url = "https://authenticator.cursor.sh"
sign_up_url = "https://authenticator.cursor.sh/sign-up"
settings_url = "https://www.cursor.com/settings"
# 获取允许的域名
allowed_domains = get_allowed_domains() # 获取允许的域名列表
if not allowed_domains:
logging.error("没有可用的域名,无法进行注册")
sys.exit(1) # 退出程序
# 提示用户选择域名使用方式
print("请选择域名使用方式:")
print("1. 指定域名")
print("2. 随机轮询域名")
while True:
try:
choice = int(input("请输入选项 (1 或 2): ").strip())
if choice in [1, 2]:
break
else:
print("无效的选项,请重新输入")
except ValueError:
print("请输入有效的数字")
selected_domains = []
if choice == 1:
# 用户指定域名
print("可用域名:")
for index, domain in enumerate(allowed_domains):
print(f"{index + 1}. {domain}")
print("请输入要使用的域名索引,以逗号分隔或范围(如 1-20):")
indices = input("例如: 1,2,3 或 1-20").strip().split(",")
selected_domains = []
for index in indices:
if '-' in index:
start, end = index.split('-')
try:
start = int(start)
end = int(end)
selected_domains.extend(allowed_domains[start - 1:end]) # 添加范围内的域名
except (ValueError, IndexError):
logging.error(f"范围输入无效: {index}")
else:
try:
idx = int(index)
selected_domains.append(allowed_domains[idx - 1]) # 添加单个域名
except (ValueError, IndexError):
logging.error(f"索引输入无效: {index}")
else:
# 随机轮询域名
selected_domains = allowed_domains
# 成功账号列表
successful_accounts = []
# 超时账号计数
timeout_accounts = 0
# 配置数量
config_count = len(selected_domains) # 使用用户选择的域名数量
for i in range(register_count):
logging.info(f"\n=== 开始注册第 {i + 1}/{register_count} 个账号 ===")
current_config_index = i % config_count # 当前使用的配置索引
logging.info(f"使用配置 {current_config_index + 1} / {config_count}") # 打印当前使用的配置和总配置
selected_domain = selected_domains[current_config_index] # 选择当前域名
logging.info(f"使用域名: {selected_domain}")
# 记录注册开始时间
registration_start_time = time.time()
# 设置注册超时时间4分钟 = 240秒
registration_timeout = 240
logging.info(f"注册超时设置为 {registration_timeout}")
# 为每个账号创建新的浏览器实例,确保账号纯净
if browser_manager:
logging.info("关闭上一个浏览器实例...")
browser_manager.quit()
logging.info("创建新的浏览器实例...")
browser_manager = BrowserManager()
# 使用选择的代理模式初始化浏览器
browser, proxy_info = browser_manager.init_browser(
user_agent,
proxy_choice=global_proxy_choice,
custom_api=global_custom_api
)
proxy_host, proxy_port, proxy_username, proxy_password, proxy_data = proxy_info
current_proxies = {
'http': f'http://{proxy_username}:{proxy_password}@{proxy_host}:{proxy_port}',
'https': f'http://{proxy_username}:{proxy_password}@{proxy_host}:{proxy_port}'
}
logging.info(f"API将使用相同代理: {proxy_host}:{proxy_port}")
logging.info(f"API将使用相同代理: {proxy_data}")
# 生成邮箱
email_generator = EmailGenerator(selected_domain=selected_domain) # 传递选定的域名
account_info = email_generator.get_account_info() # 获取账号信息
account = account_info['email'] # 使用生成的邮箱
password = account_info['password'] # 使用生成的密码
first_name = account_info['first_name'] # 使用生成的名字
last_name = account_info['last_name'] # 使用生成的姓氏
logging.info(f"生成的邮箱账号: {account}")
auto_update_cursor_auth = True
tab = browser.latest_tab
tab.run_js("try { turnstile.reset() } catch(e) { }")
logging.info("\n=== 开始注册流程 ===")
logging.info(f"正在访问登录页面: {login_url}")
tab.get(login_url)
# 检查是否超时
if check_timeout(registration_start_time):
logging.warning("放弃当前注册,继续下一个账号")
timeout_accounts += 1
continue
if sign_up_account(browser, tab, registration_start_time):
# 检查是否超时
if check_timeout(registration_start_time):
logging.warning("放弃当前注册,继续下一个账号")
timeout_accounts += 1
continue
logging.info("正在获取会话令牌...")
token = get_cursor_session_token(tab, start_time=registration_start_time)
if token:
# 检查是否超时
if check_timeout(registration_start_time):
logging.warning("放弃当前注册,继续下一个账号")
timeout_accounts += 1
continue
logging.info("更新认证信息...")
logging.info("重置机器码...")
logging.info(f"API将使用相同代理: {proxy_host}:{proxy_port}")
# 保存成功注册的账号信息
account_data = {
"email": account,
"password": password,
"token": token,
"register_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"first_name": first_name,
"last_name": last_name,
'user_agent': user_agent,
'proxy_host': proxy_host,
'proxy_port': proxy_port,
'proxy_username': proxy_username,
'proxy_password': proxy_password,
'proxy_data': proxy_data
}
logging.info("更新认证信息...")
# 添加到成功账号列表
successful_accounts.append(account_data)
# # 同步到服务器
if account_sync.sync_account(account_data):
logging.info("账号已成功同步到服务器")
else:
logging.warning("账号同步到服务器失败")
else:
logging.error("获取会话令牌失败,注册流程未完成")
# 计算本次注册用时
registration_elapsed = time.time() - registration_start_time
logging.info(f"本次注册用时: {registration_elapsed:.1f}")
# 注册间隔,避免频率过快
if i < register_count - 1: # 最后一个账号不需要等待
wait_time = random.randint(1, 4)
logging.info(f"等待 {wait_time} 秒后继续下一个注册...")
time.sleep(wait_time)
# 即使注册失败,也关闭当前浏览器实例,保证下一个注册过程使用全新实例
if browser_manager:
logging.info("关闭当前浏览器实例...")
browser_manager.quit()
browser_manager = None
# 打印注册结果统计
logging.info("\n\n=== 注册结果统计 ===")
logging.info(f"总计尝试: {register_count}")
logging.info(f"成功注册: {len(successful_accounts)}")
logging.info(f"超时注册: {timeout_accounts}")
logging.info(f"其他失败: {register_count - len(successful_accounts) - timeout_accounts}")
logging.info("所有成功注册的账号信息已保存到 successful_accounts.json")
print_end_message()
except Exception as e:
logging.error(f"程序执行出现错误: {str(e)}")
import traceback
logging.error(traceback.format_exc())
finally:
# 确保浏览器实例被正确关闭
if browser_manager:
logging.info("清理资源:正在关闭浏览器...")
try:
browser_manager.quit()
logging.info("浏览器已成功关闭")
except Exception as e:
logging.error(f"关闭浏览器时出错: {str(e)}")
logging.info("程序执行完毕")
# 使用消息框代替input函数
try:
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.withdraw() # 隐藏主窗口
messagebox.showinfo("程序执行完毕", "程序执行完毕,点击确定退出...")
root.destroy()
except Exception as e:
# 如果tkinter不可用则使用其他方式
import time
logging.info(f"无法显示消息框: {str(e)}")
print("\n程序执行完毕5秒后自动退出...")
time.sleep(5)