#!/usr/bin/env python3 """ 腾讯混元3D 邮箱验证码登录 CLI 工具 (CloakBrowser 持久化版本) 第一次输入邮箱回车后自动发送验证码 第二次输入验证码后回车自动点击登录按钮 登录状态会自动保存到 ~/.config/hunyuan3dweb/profile,下次运行无需重新登录 """ import argparse import os import sys import time from cloakbrowser import launch_persistent_context from ..config import get_profile_dir, get_cookie_path PROFILE_DIR = str(get_profile_dir()) def _extract_and_save_cookies(context): """从浏览器上下文提取 Cookie 并保存到文件""" try: cookies = context.cookies() relevant_names = {"hunyuan_user", "hunyuan_token", "hunyuan_source", "hy_user"} cookie_dict = {c["name"]: c["value"] for c in cookies if c["name"] in relevant_names} if cookie_dict: cookie_str = "; ".join(f"{k}={v}" for k, v in cookie_dict.items()) cookie_path = get_cookie_path() cookie_path.write_text(cookie_str, encoding="utf-8") print(f"Cookie 已自动保存到: {cookie_path}") return True else: print("警告: 未找到 hunyuan 相关 Cookie,API 客户端可能无法使用") except Exception as e: print(f"自动提取 Cookie 失败: {e}") return False def main(): parser = argparse.ArgumentParser(description="腾讯混元3D 邮箱验证码登录") parser.add_argument( "--no-headless", action="store_true", help="显示浏览器窗口(默认无头模式,适用于服务器)" ) args = parser.parse_args() headless = not args.no_headless # 使用持久化上下文,cookie 和登录状态会保存到 PROFILE_DIR context = None try: context = launch_persistent_context(PROFILE_DIR, headless=headless) page = context.new_page() print("正在打开腾讯混元3D...") page.goto("https://3d.hunyuan.tencent.com/", timeout=60000) page.wait_for_timeout(2000) # 检查是否已经是登录状态(没有登录按钮说明已登录) login_btn = page.locator("button").filter(has_text="登录").first if login_btn.count() == 0: print("检测到已有登录状态,无需重新登录。") print(f"当前页面: {page.url}") _extract_and_save_cookies(context) if headless: return else: # 未登录,走登录流程 login_btn.click() page.locator("text=邮箱").wait_for(state="visible", timeout=10000) # 切换到邮箱登录 email_tab = page.locator("text=邮箱").first if email_tab.count() > 0: email_tab.click() email_input.wait_for(state="visible", timeout=10000) else: print("未找到邮箱登录选项") return # 定位元素 email_input = page.locator('input[placeholder="请输入邮箱地址"]') code_input = page.locator('input[type="number"][placeholder="请输入邮箱验证码"]') send_code_btn = page.locator("a.hyc-email-login__send-code") login_submit_btn = page.locator("button.hyc-email-login__btn") checkbox = page.locator(".t-checkbox__former") # 第一次交互:输入邮箱并发送验证码 print("\n============================================") email = input("请输入邮箱地址,按回车发送验证码: ").strip() if not email: print("邮箱不能为空,退出") return email_input.fill(email) # 勾选协议(如果未勾选) if checkbox.count() > 0: is_checked = checkbox.evaluate("el => el.checked") if not is_checked: checkbox.evaluate("el => el.click()") page.wait_for_timeout(300) if send_code_btn.count() > 0: send_code_btn.click() print("已点击发送验证码,请查收邮件...") else: print("未找到发送验证码按钮") return # 第二次交互:输入验证码并登录 print("\n============================================") code = input("请输入邮箱验证码,按回车登录: ").strip() if not code: print("验证码不能为空,退出") return code_input.fill(code) # 点击登录 if login_submit_btn.count() > 0: login_submit_btn.click() print("已点击登录按钮,等待跳转...") else: print("未找到登录提交按钮") return # 等待登录成功跳转 try: page.wait_for_url(lambda url: "login" not in url, timeout=30000) print(f"\n登录成功!当前页面: {page.url}") print(f"登录状态已保存到: {os.path.abspath(PROFILE_DIR)}") _extract_and_save_cookies(context) except Exception: print("\n登录可能仍在处理中,或出现错误。请检查浏览器状态。") # 保持浏览器打开(仅非无头模式) if not headless: print("\n按 Enter 键关闭浏览器并退出...") input() finally: if context is not None: try: context.close() except Exception: pass if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n已取消") sys.exit(0)