From 1cc93ffc2296022b2d2e5c7ae4a200c06d1d8612 Mon Sep 17 00:00:00 2001 From: yeongpin Date: Thu, 13 Feb 2025 11:33:20 +0800 Subject: [PATCH] fix & optimize --- .env | 4 +- blacklist.txt | 5 -- browser.py | 48 ---------- build.spec | 4 +- control.py | 166 +---------------------------------- new_signup.py | 3 +- recaptchaPatch/manifest.json | 22 ----- recaptchaPatch/script.js | 123 -------------------------- 8 files changed, 5 insertions(+), 370 deletions(-) delete mode 100644 blacklist.txt delete mode 100644 recaptchaPatch/manifest.json delete mode 100644 recaptchaPatch/script.js diff --git a/.env b/.env index 4a325b7..6917aae 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -version=1.1.01 -VERSION=1.1.01 +version=1.2.01 +VERSION=1.2.01 diff --git a/blacklist.txt b/blacklist.txt deleted file mode 100644 index 10f9030..0000000 --- a/blacklist.txt +++ /dev/null @@ -1,5 +0,0 @@ -fr.nf -yopmail.com -1s.fr -xl.cx -fr.cr \ No newline at end of file diff --git a/browser.py b/browser.py index b03c4c9..677a6ab 100644 --- a/browser.py +++ b/browser.py @@ -32,11 +32,6 @@ class BrowserManager: extension_block_path = self.get_extension_block() co.add_extension(extension_block_path) co.set_argument("--allow-extensions-in-incognito") - - extension_recaptcha_path = self.get_extension_recaptcha() - co.add_extension(extension_recaptcha_path) - co.set_argument("--allow-extensions-in-incognito") - except FileNotFoundError as e: logging.warning(f"警告: {e}") @@ -47,35 +42,6 @@ class BrowserManager: # 基本设置 co.set_pref("credentials_enable_service", False) - co.set_pref("profile.password_manager_enabled", False) - - # 禁用自动化标志 - co.set_pref("useAutomationExtension", False) - co.set_pref("excludeSwitches", ["enable-automation"]) - - # WebGL 和 GPU 设置 - co.set_pref("webgl.disabled", False) - co.set_pref("webgl.enable_webgl2", True) - - # 设置语言和地区 - co.set_pref("intl.accept_languages", "en-US,en") - - # 基本命令行参数 - co.set_argument("--disable-blink-features=AutomationControlled") - co.set_argument("--hide-crash-restore-bubble") - co.set_argument("--no-first-run") - co.set_argument("--no-default-browser-check") - co.set_argument("--disable-popup-blocking") - - # 性能和稳定性参数 - co.set_argument("--disable-dev-shm-usage") - co.set_argument("--disable-gpu") - co.set_argument("--no-sandbox") - co.set_argument("--ignore-certificate-errors") - - # WebGL 相关参数 - co.set_argument("--use-gl=swiftshader") - co.set_argument("--enable-webgl") # 随机端口 co.auto_port() @@ -87,7 +53,6 @@ class BrowserManager: elif sys.platform == "win32": # Windows co.set_argument("--disable-software-rasterizer") - # 设置窗口大小 window_width = random.randint(1024, 1920) window_height = random.randint(768, 1080) @@ -121,19 +86,6 @@ class BrowserManager: return extension_path - def get_extension_recaptcha(self): - """获取插件路径""" - root_dir = os.getcwd() - extension_path = os.path.join(root_dir, "recaptchaPatch") - - if hasattr(sys, "_MEIPASS"): - extension_path = os.path.join(sys._MEIPASS, "recaptchaPatch") - - if not os.path.exists(extension_path): - raise FileNotFoundError(f"插件不存在: {extension_path}") - - return extension_path - def quit(self): """关闭浏览器""" if self.browser: diff --git a/build.spec b/build.spec index d5bc2ee..f55a72c 100644 --- a/build.spec +++ b/build.spec @@ -24,7 +24,6 @@ a = Analysis( binaries=[], datas=[ ('turnstilePatch', 'turnstilePatch'), - ('recaptchaPatch', 'recaptchaPatch'), ('uBlock0.chromium', 'uBlock0.chromium'), ('locales', 'locales'), ('cursor_auth.py', '.'), @@ -32,8 +31,7 @@ a = Analysis( ('cursor_register.py', '.'), ('browser.py', '.'), ('control.py', '.'), - ('.env', '.'), - ('blacklist.txt', '.') + ('.env', '.') ], hiddenimports=[ 'cursor_auth', diff --git a/control.py b/control.py index 96d36e9..8ac2ca7 100644 --- a/control.py +++ b/control.py @@ -58,97 +58,7 @@ class BrowserControl: def get_current_tab(self): """获取当前标签页""" return self.browser - - def generate_new_email(self): - """点击新的按钮生成新邮箱""" - try: - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{Style.RESET_ALL}") - new_button = self.browser.ele('xpath://button[contains(@class, "egenbut")]') - if new_button: - new_button.click() - time.sleep(1) # 等待生成 - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.generate_email_success')}{Style.RESET_ALL}") - return True - else: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.generate_email_failed')}{Style.RESET_ALL}") - return False - except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}") - return False - - def select_email_domain(self, domain_index=None): - """选择邮箱域名,如果不指定index则随机选择""" - try: - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}...{Style.RESET_ALL}") - - # 读取黑名单域名 - blacklist = [] - try: - with open('blacklist.txt', 'r', encoding='utf-8') as f: - blacklist = [line.strip().lower() for line in f if line.strip()] - except FileNotFoundError: - # 如果文件不存在,创建一个包含已知黑名单域名的文件 - with open('blacklist.txt', 'w', encoding='utf-8') as f: - f.write("fr.nf\nyopmail.com\n1s.fr\nfr.cr") - blacklist = ["fr.nf", "yopmail.com", "1s.fr", "fr.cr"] - - # 找到下拉框 - select_element = self.browser.ele('xpath://select[@id="seldom"]') - if select_element: - # 获取所有选项 - all_options = [] - new_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 新的 --"]/option') - other_options = self.browser.eles('xpath://select[@id="seldom"]/optgroup[@label="-- 其他 --"]/option') - all_options.extend(new_options) - all_options.extend(other_options) - - if all_options: - max_attempts = 5 - attempt = 0 - - while attempt < max_attempts: - if domain_index is None: - domain_index = random.randint(0, len(all_options) - 1) - - if domain_index < len(all_options): - selected_domain = all_options[domain_index].text.lower() - - # 检查域名是否在黑名单中 - is_blacklisted = False - for blocked_domain in blacklist: - if blocked_domain in selected_domain: - print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('control.blocked_domain', domain=blocked_domain)}{Style.RESET_ALL}") - domain_index = None - attempt += 1 - is_blacklisted = True - break - - if is_blacklisted: - continue - - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.select_email_domain')}: {selected_domain}{Style.RESET_ALL}") - - # 点击选择 - all_options[domain_index].click() - time.sleep(1) - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.select_email_domain_success')}{Style.RESET_ALL}") - return True - - attempt += 1 - - print(f"{Fore.RED}{EMOJI['ERROR']} 无法找到可用的域名{Style.RESET_ALL}") - return False - - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_available_domain_options', count=len(all_options))}{Style.RESET_ALL}") - return False - else: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_domain_select_box')}{Style.RESET_ALL}") - return False - - except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.select_email_domain_failed', error=str(e))}{Style.RESET_ALL}") - return False - + def wait_for_page_load(self, seconds=2): """等待页面加载""" time.sleep(seconds) @@ -164,80 +74,6 @@ class BrowserControl: print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.browser_error', error=str(e))}{Style.RESET_ALL}") return False - def copy_and_get_email(self): - """获取邮箱地址""" - try: - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.generate_email')}...{Style.RESET_ALL}") - - # 等待元素加载 - time.sleep(1) - - # 获取邮箱名称 - try: - email_div = self.browser.ele('xpath://div[@class="segen"]//div[contains(@style, "color: #e5e5e5")]') - if email_div: - email_name = email_div.text.split()[0] - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.get_email_name')}: {email_name}{Style.RESET_ALL}") - else: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed')}{Style.RESET_ALL}") - return None - except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_name_failed', error=str(e))}{Style.RESET_ALL}") - return None - - # 直接使用上一步选择的域名 - try: - domain = self.browser.ele('xpath://select[@id="seldom"]').value - if not domain: # 如果获取不到value,尝试获取选中的选项文本 - selected_option = self.browser.ele('xpath://select[@id="seldom"]/option[1]') - domain = selected_option.text if selected_option else "@yopmail.com" # 使用默认域名作为后备 - except: - domain = "@yopmail.com" # 如果出错,使用默认域名 - - # 组合完整邮箱地址 - full_email = f"{email_name}{domain}" - print(f"{Fore.GREEN}{EMOJI['MAIL']} {self.translator.get('control.get_email_address')}: {full_email}{Style.RESET_ALL}") - return full_email - - except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.get_email_address_failed', error=str(e))}{Style.RESET_ALL}") - return None - - def view_mailbox(self): - """点击查看邮箱按钮""" - try: - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.enter_mailbox')}...{Style.RESET_ALL}") - view_button = self.browser.ele('xpath://button[contains(@class, "egenbut") and contains(.//span, "查看邮箱")]') - if view_button: - view_button.click() - time.sleep(2) # 等待页面加载 - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.enter_mailbox_success')}{Style.RESET_ALL}") - return True - else: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_view_mailbox_button')}{Style.RESET_ALL}") - return False - except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.enter_mailbox_failed', error=str(e))}{Style.RESET_ALL}") - return False - - def refresh_mailbox(self): - """刷新邮箱获取最新信息""" - try: - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('control.refresh_mailbox')}...{Style.RESET_ALL}") - refresh_button = self.browser.ele('xpath://button[@id="refresh"]') - if refresh_button: - refresh_button.click() - time.sleep(2) # 等待刷新完成 - print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('control.refresh_mailbox_success')}{Style.RESET_ALL}") - return True - else: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.no_refresh_button')}{Style.RESET_ALL}") - return False - except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('control.refresh_mailbox_failed', error=str(e))}{Style.RESET_ALL}") - return False - - def get_verification_code(self): """从邮件中获取验证码""" try: diff --git a/new_signup.py b/new_signup.py index e8bd655..3b46c57 100644 --- a/new_signup.py +++ b/new_signup.py @@ -100,12 +100,11 @@ def setup_driver(translator=None): # 使用无痕模式 co.set_argument("--incognito") - co.set_argument("--headless=new") # 设置随机端口 co.auto_port() - # 使用有头模式 + # 使用有头模式(一定要设置为False,模擬人類操作) co.headless(False) try: diff --git a/recaptchaPatch/manifest.json b/recaptchaPatch/manifest.json deleted file mode 100644 index 746eee3..0000000 --- a/recaptchaPatch/manifest.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "manifest_version": 3, - "name": "Recaptcha Blocker", - "version": "1.0", - "description": "Blocks reCAPTCHA from loading", - "content_scripts": [ - { - "matches": ["*://yopmail.com/zh/wm*"], - "js": ["script.js"], - "run_at": "document_start", - "all_frames": true - } - ], - "permissions": [ - "webNavigation", - "activeTab" - ], - "host_permissions": [ - "*://yopmail.com/*", - "*://*.google.com/*" - ] -} \ No newline at end of file diff --git a/recaptchaPatch/script.js b/recaptchaPatch/script.js deleted file mode 100644 index 517e3df..0000000 --- a/recaptchaPatch/script.js +++ /dev/null @@ -1,123 +0,0 @@ -// Debug logging function -function log(message) { - console.log(`[reCAPTCHA Bypass] ${new Date().toISOString()}: ${message}`); -} - -// Function to get element by selector -function qSelector(selector) { - return document.querySelector(selector); -} - -// Constants -const MAX_ATTEMPTS = 1; -const SELECTORS = { - CHECK_BOX: ".recaptcha-checkbox-border", - AUDIO_BUTTON: "#recaptcha-audio-button", - PLAY_BUTTON: ".rc-audiochallenge-play-button .rc-button-default", - AUDIO_SOURCE: "#audio-source", - IMAGE_SELECT: "#rc-imageselect", - RESPONSE_FIELD: ".rc-audiochallenge-response-field", - AUDIO_ERROR_MESSAGE: ".rc-audiochallenge-error-message", - AUDIO_RESPONSE: "#audio-response", - RELOAD_BUTTON: "#recaptcha-reload-button", - RECAPTCHA_STATUS: "#recaptcha-accessible-status", - DOSCAPTCHA: ".rc-doscaptcha-body", - VERIFY_BUTTON: "#recaptcha-verify-button" -}; - -// Function to check if element is hidden -function isHidden(el) { - return (el.offsetParent === null); -} - -// Function to handle the bypass process -async function bypassRecaptcha() { - try { - log('Starting bypass process...'); - log('Waiting 3 seconds before starting...'); - await new Promise(resolve => setTimeout(resolve, 3000)); - - let solved = false; - let checkBoxClicked = false; - let requestCount = 0; - - const recaptchaInitialStatus = qSelector(SELECTORS.RECAPTCHA_STATUS) ? - qSelector(SELECTORS.RECAPTCHA_STATUS).innerText : ""; - - log('Initial reCAPTCHA status: ' + recaptchaInitialStatus); - - // Main bypass logic - try { - if (!checkBoxClicked && qSelector(SELECTORS.CHECK_BOX) && - !isHidden(qSelector(SELECTORS.CHECK_BOX))) { - log('Clicking checkbox...'); - qSelector(SELECTORS.CHECK_BOX).click(); - checkBoxClicked = true; - } - - // Check if the captcha is solved - if (qSelector(SELECTORS.RECAPTCHA_STATUS) && - (qSelector(SELECTORS.RECAPTCHA_STATUS).innerText != recaptchaInitialStatus)) { - solved = true; - log('SOLVED!'); - } - - if (requestCount > MAX_ATTEMPTS) { - log('Attempted Max Retries. Stopping the solver'); - solved = true; - } - - // Stop solving when Automated queries message is shown - if (qSelector(SELECTORS.DOSCAPTCHA) && - qSelector(SELECTORS.DOSCAPTCHA).innerText.length > 0) { - log('Automated Queries Detected'); - } - - } catch (err) { - log(`Error in main bypass logic: ${err.message}`); - } - - log('Bypass process completed'); - - // If not solved, retry after delay - if (!solved && requestCount < MAX_ATTEMPTS) { - requestCount++; - log(`Retrying... Attempt ${requestCount} of ${MAX_ATTEMPTS}`); - setTimeout(bypassRecaptcha, 2000); - } - - } catch (e) { - log(`Bypass failed: ${e.message}`); - } -} - -// Create a MutationObserver to watch for reCAPTCHA elements -log('Setting up MutationObserver...'); -const observer = new MutationObserver((mutations) => { - mutations.forEach((mutation) => { - mutation.addedNodes.forEach((node) => { - if (node.nodeType === 1 && // Element node - ((node.tagName === 'SCRIPT' && node.src && node.src.includes('recaptcha')) || - (node.tagName === 'IFRAME' && node.src && node.src.includes('recaptcha')))) { - log(`Detected new reCAPTCHA element: ${node.tagName} - ${node.src}`); - bypassRecaptcha(); - } - }); - }); -}); - -// Start observing -observer.observe(document, { - childList: true, - subtree: true -}); -log('MutationObserver started'); - -// Run on page load -if (document.readyState === 'loading') { - log('Document still loading, waiting for DOMContentLoaded'); - document.addEventListener('DOMContentLoaded', bypassRecaptcha); -} else { - log('Document already loaded, starting bypass process'); - bypassRecaptcha(); -} \ No newline at end of file