Spaces:
Paused
Paused
| import sys | |
| import time | |
| import random | |
| import string | |
| import re | |
| print("[-] 系统正在启动 v2.5 (Simulated Typing)...") | |
| try: | |
| import undetected_chromedriver as uc | |
| from selenium.webdriver.common.by import By | |
| from selenium.webdriver.support.ui import WebDriverWait | |
| from selenium.webdriver.support import expected_conditions as EC | |
| from selenium.webdriver.common.keys import Keys | |
| from selenium.webdriver.common.action_chains import ActionChains | |
| import requests | |
| from requests.adapters import HTTPAdapter | |
| from urllib3.util.retry import Retry | |
| except ImportError: | |
| print("[X] 缺少库。请运行: pip install selenium undetected-chromedriver requests") | |
| sys.exit(1) | |
| # ================= 配置区 ================= | |
| TOTAL_ACCOUNTS = 10 | |
| MAIL_API = "https://mail.chatgpt.org.uk" | |
| MAIL_KEY = "gpt-test" | |
| OUTPUT_FILE = "dreamina_accounts.txt" | |
| DREAMINA_URL = "https://dreamina.capcut.com/ai-tool/home" | |
| # ================= 工具函数 ================= | |
| def log(msg): | |
| print(f"[{time.strftime('%H:%M:%S')}] {msg}") | |
| def create_http_session(): | |
| s = requests.Session() | |
| s.mount("https://", HTTPAdapter(max_retries=Retry(total=3, backoff_factor=1))) | |
| return s | |
| http = create_http_session() | |
| def generate_password(): | |
| chars = string.ascii_letters + string.digits + "!@#$%" | |
| return ''.join(random.choice(chars) for _ in range(14)) | |
| def create_temp_email(): | |
| try: | |
| log("正在申请邮箱...") | |
| r = http.get(f"{MAIL_API}/api/generate-email", headers={"X-API-Key": MAIL_KEY}, timeout=20) | |
| if r.json().get('success'): return r.json()['data']['email'] | |
| except Exception as e: log(f"邮箱异常: {e}") | |
| return None | |
| def wait_for_code(email): | |
| log(f"等待 {email} 的验证码 (60s)...") | |
| start = time.time() | |
| seen = set() | |
| # 匹配模式: "code: XXXXXX" 或 "code is XXXXXX" (支持字母+数字混合) | |
| regex_pattern = r'verification code[:\s]+([A-Z0-9]{6})' | |
| while time.time() - start < 60: | |
| try: | |
| r = http.get(f"{MAIL_API}/api/emails", params={"email": email}, headers={"X-API-Key": MAIL_KEY}) | |
| data = r.json().get('data', {}).get('emails', []) | |
| if data: | |
| content = data[0].get('content') or data[0].get('html_content') or '' | |
| text_content = re.sub('<[^<]+?>', ' ', content) # 清洗HTML | |
| if text_content and text_content not in seen: | |
| seen.add(text_content) | |
| match = re.search(regex_pattern, text_content, re.IGNORECASE) | |
| if match: | |
| code = match.group(1) | |
| log(f"捕获混合验证码: {code}") | |
| return code | |
| except: pass | |
| time.sleep(5) | |
| return None | |
| # ================= 验证码填充逻辑 (v2.5 新增) ================= | |
| def fill_split_code(driver, code): | |
| """专门处理 6 位分割输入框""" | |
| actions = ActionChains(driver) | |
| # 策略 A: 尝试找到所有输入框并一一填入 | |
| try: | |
| inputs = driver.find_elements(By.XPATH, "//input") | |
| # 过滤出可能是验证码框的 input (通常都很短) | |
| code_inputs = [inp for inp in inputs if inp.is_displayed() and inp.get_attribute("type") != "hidden"] | |
| # 如果恰好找到6个可见的框(大概率是验证码框) | |
| # 或者页面上只有极少的输入框(去掉了搜索栏之类的) | |
| target_inputs = [] | |
| for inp in code_inputs: | |
| # 排除掉搜索框、邮箱框等,只留那种很短的框 | |
| if "search" not in (inp.get_attribute("placeholder") or "").lower(): | |
| target_inputs.append(inp) | |
| # 如果数量接近6个,尝试一一填入 | |
| if 4 <= len(target_inputs) <= 6: | |
| log(f"识别到 {len(target_inputs)} 个分割输入框,尝试精准填充...") | |
| for i, char in enumerate(code): | |
| if i < len(target_inputs): | |
| target_inputs[i].send_keys(char) | |
| return True | |
| except: pass | |
| # 策略 B (通用): 聚焦第一个框,然后也就是 "盲打" | |
| log("使用键盘模拟输入 (ActionChains)...") | |
| try: | |
| # 你的截图显示焦点已经在第一个格子里了,所以直接通过键盘敲击 | |
| # 为了保险,先点一下页面中心空白处,或者尝试点第一个 input | |
| try: | |
| first_input = driver.find_element(By.TAG_NAME, "input") | |
| driver.execute_script("arguments[0].focus();", first_input) | |
| first_input.click() | |
| except: | |
| # 如果找不到特定的,就点击 body 确保窗口激活 | |
| driver.find_element(By.TAG_NAME, "body").click() | |
| time.sleep(0.5) | |
| # 逐个敲击按键 | |
| for char in code: | |
| actions.send_keys(char).perform() | |
| time.sleep(0.1) # 稍微慢一点,让网页反应过来自动跳格 | |
| return True | |
| except Exception as e: | |
| log(f"模拟输入失败: {e}") | |
| return False | |
| # ================= 核心流程 ================= | |
| def register_one(driver): | |
| email = create_temp_email() | |
| if not email: return False | |
| password = generate_password() | |
| wait = WebDriverWait(driver, 20) | |
| try: | |
| log("加载主页...") | |
| driver.get(DREAMINA_URL) | |
| time.sleep(3) | |
| # 1. 登录/注册入口 | |
| log("尝试寻找并点击登录/注册入口...") | |
| try: | |
| # 增加显式等待,并同时查找 Sign in 和 Sign up | |
| xpath = "//*[contains(text(), 'Sign in') or contains(text(), 'Sign up')]" | |
| btns = wait.until(EC.presence_of_all_elements_located((By.XPATH, xpath))) | |
| clicked = False | |
| for b in btns: | |
| if b.is_displayed(): | |
| # log(f"发现可见按钮: '{b.text}',尝试点击...") | |
| driver.execute_script("arguments[0].click();", b) | |
| clicked = True | |
| break | |
| if not clicked: | |
| log("未找到可见的 Sign in/Sign up 按钮") | |
| except Exception as e: | |
| log(f"点击入口操作跳过或失败: {e}") | |
| # 2. 选择 Email 方式 | |
| time.sleep(2) | |
| try: | |
| email_btn = wait.until(EC.presence_of_element_located((By.XPATH, "//*[contains(text(), 'Continue with email')]"))) | |
| driver.execute_script("arguments[0].click();", email_btn) | |
| except: pass | |
| # 3. 智能切换 Sign up | |
| time.sleep(2) | |
| if "Welcome back" in driver.page_source: | |
| # log("切换至注册模式 (Sign up)...") | |
| try: | |
| switch_btn = driver.find_element(By.XPATH, "//span[contains(text(), 'Sign up')] | //a[contains(text(), 'Sign up')]") | |
| driver.execute_script("arguments[0].click();", switch_btn) | |
| time.sleep(2) | |
| except: pass | |
| # 4. 填写邮箱 & 密码 | |
| log(f"填写邮箱: {email}") | |
| try: | |
| email_inp = wait.until(EC.presence_of_element_located((By.XPATH, "//input[contains(@placeholder, 'email') or @type='email']"))) | |
| email_inp.clear() | |
| email_inp.send_keys(email) | |
| pass_inp = driver.find_elements(By.XPATH, "//input[@type='password']") | |
| if pass_inp: | |
| pass_inp[0].send_keys(password) | |
| except: return False | |
| # 5. 点击 Continue | |
| log("点击 Continue...") | |
| try: | |
| time.sleep(1) | |
| cont_btn = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Continue') or contains(text(), 'Sign up')]"))) | |
| cont_btn.click() | |
| except: | |
| # 暴力点击 Enter 键 | |
| ActionChains(driver).send_keys(Keys.ENTER).perform() | |
| # 6. 等待并填入验证码 | |
| time.sleep(3) | |
| code = wait_for_code(email) | |
| if code: | |
| log(f"开始填入验证码: {code}") | |
| fill_split_code(driver, code) | |
| # 填完后,通常会自动跳转,或者是通过 Next 按钮 | |
| time.sleep(2) | |
| try: | |
| next_btn = driver.find_element(By.XPATH, "//button[contains(text(), 'Next') or contains(text(), 'Sign up') or contains(text(), 'Confirm')]") | |
| if next_btn.is_displayed(): | |
| next_btn.click() | |
| except: pass | |
| # 7. 生日处理 | |
| time.sleep(4) | |
| page_content = driver.page_source.lower() | |
| if "birthday" in page_content or len(driver.find_elements(By.TAG_NAME, "select")) >= 1: | |
| log("填写生日...") | |
| try: | |
| actions = ActionChains(driver) | |
| # --- 1. 年份 (Year) --- | |
| # 寻找 placeholder 为 YYYY 或者 4位数的输入框,或者直接找第一个 input | |
| try: | |
| # 尝试通过 placeholder 定位 | |
| year_input = driver.find_element(By.XPATH, "//input[contains(@placeholder, 'YYYY') or contains(@placeholder, 'Year')]") | |
| except: | |
| # 兜底:找页面上第一个可见的 input | |
| inputs = driver.find_elements(By.TAG_NAME, "input") | |
| year_input = next((i for i in inputs if i.is_displayed()), None) | |
| if year_input: | |
| # log("填写年份...") | |
| driver.execute_script("arguments[0].click();", year_input) | |
| time.sleep(0.3) | |
| year_input.send_keys(Keys.CONTROL, "a") | |
| year_input.send_keys(Keys.BACK_SPACE) | |
| # 随机年份 1995-2005 | |
| rand_year = str(random.randint(1995, 2005)) | |
| year_input.send_keys(rand_year) | |
| time.sleep(0.5) | |
| # --- 2. 月份 (Month) --- | |
| # log("选择月份...") | |
| try: | |
| # 尝试点击显示 "Month" 的区域 | |
| month_trigger = driver.find_element(By.XPATH, "//*[text()='Month']") | |
| driver.execute_script("arguments[0].click();", month_trigger) | |
| time.sleep(1) | |
| # 随机月份 | |
| months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] | |
| rand_month = random.choice(months) | |
| # log(f"随机选择月份: {rand_month}") | |
| # 使用 contains text 以防有空格 | |
| month_opt = driver.find_element(By.XPATH, f"//*[contains(text(), '{rand_month}')]") | |
| driver.execute_script("arguments[0].click();", month_opt) | |
| except Exception as e: | |
| # log(f"点击 Month 失败,尝试键盘流: {e}") | |
| # 备用:Tab 过去,回车展开,下移选中 | |
| actions.send_keys(Keys.TAB).perform() | |
| time.sleep(0.2) | |
| actions.send_keys(Keys.ENTER).perform() | |
| time.sleep(0.2) | |
| actions.send_keys(Keys.DOWN).perform() | |
| actions.send_keys(Keys.ENTER).perform() | |
| time.sleep(1) | |
| # --- 3. 日期 (Day) --- | |
| # log("选择日期...") | |
| try: | |
| # 尝试点击显示 "Day" 的区域 | |
| day_trigger = driver.find_element(By.XPATH, "//*[text()='Day']") | |
| driver.execute_script("arguments[0].click();", day_trigger) | |
| time.sleep(1) | |
| # 随机日期 1-28 (保守起见,避免大小月问题) | |
| rand_day = str(random.randint(1, 28)) | |
| # log(f"随机选择日期: {rand_day}") | |
| # 在下拉列表中选择 | |
| # 避免匹配到其他文本,尽量精确 | |
| day_opt = driver.find_element(By.XPATH, f"//div[text()='{rand_day}'] | //li[text()='{rand_day}'] | //span[text()='{rand_day}']") | |
| driver.execute_script("arguments[0].click();", day_opt) | |
| except Exception as e: | |
| # log(f"点击 Day 失败,尝试键盘流: {e}") | |
| actions.send_keys(Keys.TAB).perform() | |
| time.sleep(0.2) | |
| actions.send_keys(Keys.ENTER).perform() | |
| time.sleep(0.2) | |
| actions.send_keys(Keys.DOWN).perform() # 选第1个 | |
| actions.send_keys(Keys.DOWN).perform() # 选第2个 | |
| actions.send_keys(Keys.ENTER).perform() | |
| # --- 4. 提交 --- | |
| time.sleep(1) | |
| # log("尝试点击 Next...") | |
| # 尝试多种定位方式,因为 Next 可能是 div/span 而不是 button | |
| xpath_candidates = [ | |
| "//button[contains(text(), 'Next')]", | |
| "//div[contains(text(), 'Next')]", | |
| "//span[contains(text(), 'Next')]", | |
| "//button[@type='submit']", | |
| "//*[text()='Next']" | |
| ] | |
| clicked_next = False | |
| for xp in xpath_candidates: | |
| try: | |
| elements = driver.find_elements(By.XPATH, xp) | |
| for el in elements: | |
| if el.is_displayed(): | |
| # log(f"找到可见 Next 按钮 ({xp}),点击...") | |
| driver.execute_script("arguments[0].click();", el) | |
| clicked_next = True | |
| break | |
| except: pass | |
| if clicked_next: break | |
| if not clicked_next: | |
| # log("未找到明确的 Next 按钮,尝试键盘 Enter...") | |
| actions.send_keys(Keys.ENTER).perform() | |
| except Exception as e: | |
| log(f"生日填写出错: {e}") | |
| # 8. 成功判定 (Session 刷新模式) | |
| log("等待 Session 刷新 (约 30s)...") | |
| start_wait = time.time() | |
| found_sess = None | |
| while time.time() - start_wait < 30: | |
| cookies = driver.get_cookies() | |
| sess = next((c['value'] for c in cookies if c['name'] == 'sessionid'), None) | |
| if sess: | |
| found_sess = sess | |
| break | |
| time.sleep(2) | |
| if found_sess: | |
| log(f"SUCCESS! Session: {found_sess[:10]}...") | |
| with open(OUTPUT_FILE, "a") as f: | |
| f.write(f"{email}|{password}|{found_sess}\n") | |
| return True | |
| else: | |
| log("未获取到 Session,注册可能未完成") | |
| return False | |
| except Exception as e: | |
| log(f"错误: {e}") | |
| return False | |
| # ================= 入口 ================= | |
| if __name__ == "__main__": | |
| # 屏蔽 undetected_chromedriver 的退出报错 | |
| def suppress_exception(exc_type, exc_value, exc_traceback): | |
| if issubclass(exc_type, OSError) and "[WinError 6]" in str(exc_value): | |
| return | |
| sys.__excepthook__(exc_type, exc_value, exc_traceback) | |
| sys.excepthook = suppress_exception | |
| print(f"[-] 计划注册账号数: {TOTAL_ACCOUNTS}") | |
| for i in range(TOTAL_ACCOUNTS): | |
| log(f"=== 开始注册第 {i+1}/{TOTAL_ACCOUNTS} 个账号 ===") | |
| opts = uc.ChromeOptions() | |
| opts.add_argument("--no-first-run") | |
| opts.add_argument("--disable-popup-blocking") | |
| # 每次使用新的用户数据目录,确保环境隔离(可选,如果网站不严格检查指纹,可以直接重启浏览器) | |
| # opts.add_argument(f"--user-data-dir=./chrome_profile_{i}") | |
| driver = None | |
| try: | |
| driver = uc.Chrome(options=opts, suppress_welcome=True) | |
| if register_one(driver): | |
| log(f"第 {i+1} 个账号注册成功") | |
| else: | |
| log(f"第 {i+1} 个账号注册失败") | |
| except Exception as e: | |
| if "[WinError 6]" not in str(e): | |
| log(f"运行时错误: {e}") | |
| finally: | |
| if driver: | |
| try: | |
| driver.quit() | |
| except OSError: pass | |
| # 账号间稍微等待,避免请求过快 | |
| if i < TOTAL_ACCOUNTS - 1: | |
| wait_time = random.randint(5, 10) | |
| log(f"等待 {wait_time} 秒后继续下一个...") | |
| time.sleep(wait_time) | |
| print("[*] 所有任务已结束") | |