diff --git a/auto_gpt_team.py b/auto_gpt_team.py index f4eca8d..3bcc16e 100644 --- a/auto_gpt_team.py +++ b/auto_gpt_team.py @@ -198,41 +198,51 @@ def inject_fingerprint(page, fingerprint: dict): plat = fingerprint.get("platform", "Win32") screen = fingerprint.get("screen", {"width": 1920, "height": 1080}) + # 使用 try-catch 包裹每个属性定义,避免 Linux 上属性不可重定义的错误 js_script = f''' - // 伪装 WebGL 指纹 - const getParameterProxyHandler = {{ - apply: function(target, thisArg, args) {{ - const param = args[0]; - if (param === 37445) {{ return "{webgl_vendor}"; }} - if (param === 37446) {{ return "{webgl_renderer}"; }} - return Reflect.apply(target, thisArg, args); - }} - }}; - const originalGetParameter = WebGLRenderingContext.prototype.getParameter; - WebGLRenderingContext.prototype.getParameter = new Proxy(originalGetParameter, getParameterProxyHandler); - if (typeof WebGL2RenderingContext !== 'undefined') {{ - const originalGetParameter2 = WebGL2RenderingContext.prototype.getParameter; - WebGL2RenderingContext.prototype.getParameter = new Proxy(originalGetParameter2, getParameterProxyHandler); - }} - // 伪装 platform - Object.defineProperty(navigator, 'platform', {{ get: () => "{plat}" }}); - // 伪装屏幕分辨率 - Object.defineProperty(screen, 'width', {{ get: () => {screen["width"]} }}); - Object.defineProperty(screen, 'height', {{ get: () => {screen["height"]} }}); - Object.defineProperty(screen, 'availWidth', {{ get: () => {screen["width"]} }}); - Object.defineProperty(screen, 'availHeight', {{ get: () => {screen["height"]} }}); - // 隐藏 webdriver 特征 - Object.defineProperty(navigator, 'webdriver', {{ get: () => undefined }}); - // 伪装 languages - Object.defineProperty(navigator, 'languages', {{ get: () => ["zh-CN", "zh", "en-US", "en"] }}); - // 伪装 plugins - Object.defineProperty(navigator, 'plugins', {{ - get: () => [ - {{ name: "Chrome PDF Plugin", filename: "internal-pdf-viewer" }}, - {{ name: "Chrome PDF Viewer", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai" }}, - {{ name: "Native Client", filename: "internal-nacl-plugin" }} - ] - }}); + (function() {{ + // 伪装 WebGL 指纹 + try {{ + const getParameterProxyHandler = {{ + apply: function(target, thisArg, args) {{ + const param = args[0]; + if (param === 37445) return "{webgl_vendor}"; + if (param === 37446) return "{webgl_renderer}"; + return Reflect.apply(target, thisArg, args); + }} + }}; + const originalGetParameter = WebGLRenderingContext.prototype.getParameter; + WebGLRenderingContext.prototype.getParameter = new Proxy(originalGetParameter, getParameterProxyHandler); + if (typeof WebGL2RenderingContext !== 'undefined') {{ + const originalGetParameter2 = WebGL2RenderingContext.prototype.getParameter; + WebGL2RenderingContext.prototype.getParameter = new Proxy(originalGetParameter2, getParameterProxyHandler); + }} + }} catch(e) {{}} + // 伪装 platform + try {{ Object.defineProperty(navigator, 'platform', {{ get: () => "{plat}", configurable: true }}); }} catch(e) {{}} + // 伪装屏幕分辨率 + try {{ + Object.defineProperty(screen, 'width', {{ get: () => {screen["width"]}, configurable: true }}); + Object.defineProperty(screen, 'height', {{ get: () => {screen["height"]}, configurable: true }}); + Object.defineProperty(screen, 'availWidth', {{ get: () => {screen["width"]}, configurable: true }}); + Object.defineProperty(screen, 'availHeight', {{ get: () => {screen["height"]}, configurable: true }}); + }} catch(e) {{}} + // 隐藏 webdriver 特征 + try {{ Object.defineProperty(navigator, 'webdriver', {{ get: () => undefined, configurable: true }}); }} catch(e) {{}} + // 伪装 languages + try {{ Object.defineProperty(navigator, 'languages', {{ get: () => ["zh-CN", "zh", "en-US", "en"], configurable: true }}); }} catch(e) {{}} + // 伪装 plugins + try {{ + Object.defineProperty(navigator, 'plugins', {{ + get: () => [ + {{ name: "Chrome PDF Plugin", filename: "internal-pdf-viewer" }}, + {{ name: "Chrome PDF Viewer", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai" }}, + {{ name: "Native Client", filename: "internal-nacl-plugin" }} + ], + configurable: true + }}); + }} catch(e) {{}} + }})(); ''' page.run_js(js_script) diff --git a/browser_automation.py b/browser_automation.py index 7134cc3..90a7cd5 100644 --- a/browser_automation.py +++ b/browser_automation.py @@ -297,64 +297,62 @@ def _inject_fingerprint(page: ChromiumPage, fingerprint: dict): platform = fingerprint.get("platform", "Win32") screen = fingerprint.get("screen", {"width": 1920, "height": 1080}) - # 注入指纹伪装脚本 + # 注入指纹伪装脚本 (使用 try-catch 避免属性不可重定义的错误) js_script = f''' - // 伪装 WebGL 指纹 - const getParameterProxyHandler = {{ - apply: function(target, thisArg, args) {{ - const param = args[0]; - const gl = thisArg; - // UNMASKED_VENDOR_WEBGL - if (param === 37445) {{ - return "{webgl_vendor}"; + (function() {{ + // 伪装 WebGL 指纹 + try {{ + const getParameterProxyHandler = {{ + apply: function(target, thisArg, args) {{ + const param = args[0]; + if (param === 37445) return "{webgl_vendor}"; + if (param === 37446) return "{webgl_renderer}"; + return Reflect.apply(target, thisArg, args); + }} + }}; + const originalGetParameter = WebGLRenderingContext.prototype.getParameter; + WebGLRenderingContext.prototype.getParameter = new Proxy(originalGetParameter, getParameterProxyHandler); + if (typeof WebGL2RenderingContext !== 'undefined') {{ + const originalGetParameter2 = WebGL2RenderingContext.prototype.getParameter; + WebGL2RenderingContext.prototype.getParameter = new Proxy(originalGetParameter2, getParameterProxyHandler); }} - // UNMASKED_RENDERER_WEBGL - if (param === 37446) {{ - return "{webgl_renderer}"; - }} - return Reflect.apply(target, thisArg, args); - }} - }}; + }} catch(e) {{}} - // 代理 WebGL getParameter - const originalGetParameter = WebGLRenderingContext.prototype.getParameter; - WebGLRenderingContext.prototype.getParameter = new Proxy(originalGetParameter, getParameterProxyHandler); + // 伪装 platform + try {{ + Object.defineProperty(navigator, 'platform', {{ get: () => "{platform}", configurable: true }}); + }} catch(e) {{}} - // 代理 WebGL2 getParameter - if (typeof WebGL2RenderingContext !== 'undefined') {{ - const originalGetParameter2 = WebGL2RenderingContext.prototype.getParameter; - WebGL2RenderingContext.prototype.getParameter = new Proxy(originalGetParameter2, getParameterProxyHandler); - }} + // 伪装屏幕分辨率 + try {{ + Object.defineProperty(screen, 'width', {{ get: () => {screen["width"]}, configurable: true }}); + Object.defineProperty(screen, 'height', {{ get: () => {screen["height"]}, configurable: true }}); + Object.defineProperty(screen, 'availWidth', {{ get: () => {screen["width"]}, configurable: true }}); + Object.defineProperty(screen, 'availHeight', {{ get: () => {screen["height"]}, configurable: true }}); + }} catch(e) {{}} - // 伪装 platform - Object.defineProperty(navigator, 'platform', {{ - get: () => "{platform}" - }}); + // 隐藏 webdriver 特征 + try {{ + Object.defineProperty(navigator, 'webdriver', {{ get: () => undefined, configurable: true }}); + }} catch(e) {{}} - // 伪装屏幕分辨率 - Object.defineProperty(screen, 'width', {{ get: () => {screen["width"]} }}); - Object.defineProperty(screen, 'height', {{ get: () => {screen["height"]} }}); - Object.defineProperty(screen, 'availWidth', {{ get: () => {screen["width"]} }}); - Object.defineProperty(screen, 'availHeight', {{ get: () => {screen["height"]} }}); + // 伪装 languages + try {{ + Object.defineProperty(navigator, 'languages', {{ get: () => ["zh-CN", "zh", "en-US", "en"], configurable: true }}); + }} catch(e) {{}} - // 隐藏 webdriver 特征 - Object.defineProperty(navigator, 'webdriver', {{ - get: () => undefined - }}); - - // 伪装 languages (保持中文) - Object.defineProperty(navigator, 'languages', {{ - get: () => ["zh-CN", "zh", "en-US", "en"] - }}); - - // 伪装 plugins (模拟真实浏览器) - Object.defineProperty(navigator, 'plugins', {{ - get: () => [ - {{ name: "Chrome PDF Plugin", filename: "internal-pdf-viewer" }}, - {{ name: "Chrome PDF Viewer", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai" }}, - {{ name: "Native Client", filename: "internal-nacl-plugin" }} - ] - }}); + // 伪装 plugins + try {{ + Object.defineProperty(navigator, 'plugins', {{ + get: () => [ + {{ name: "Chrome PDF Plugin", filename: "internal-pdf-viewer" }}, + {{ name: "Chrome PDF Viewer", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai" }}, + {{ name: "Native Client", filename: "internal-nacl-plugin" }} + ], + configurable: true + }}); + }} catch(e) {{}} + }})(); ''' page.run_js(js_script) diff --git a/run.py b/run.py index e1e220e..267b5d6 100644 --- a/run.py +++ b/run.py @@ -773,6 +773,8 @@ def process_accounts_concurrent( if max_workers is None: max_workers = CONCURRENT_WORKERS + + stagger_delay = 2.0 # 线程错开启动间隔 (秒) # 过滤已完成的账号 pending_accounts = [acc for acc in accounts if acc.get("status") != "completed"] @@ -784,7 +786,7 @@ def process_accounts_concurrent( total = len(pending_accounts) actual_workers = min(max_workers, total) - log.section(f"并发处理 {total} 个账号 (并发数: {actual_workers})") + log.section(f"并发处理 {total} 个账号 (并发数: {actual_workers}, 间隔: {stagger_delay}s)") # 启动进度跟踪 progress_start(team_name, total, team_index, teams_total, include_owner) @@ -793,16 +795,26 @@ def process_accounts_concurrent( completed_count = 0 with ThreadPoolExecutor(max_workers=actual_workers) as executor: - # 提交所有任务 - future_to_account = { - executor.submit( + # 错开提交任务,每个任务间隔 stagger_delay 秒 + future_to_account = {} + for i, account in enumerate(pending_accounts): + if _shutdown_requested: + break + + worker_id = i % actual_workers + 1 + log.info(f"[Worker-{worker_id}] 启动任务: {account['email']}", icon="start") + + future = executor.submit( _process_single_account_worker, account, team_name, - i % actual_workers + 1 - ): account - for i, account in enumerate(pending_accounts) - } + worker_id + ) + future_to_account[future] = account + + # 错开启动,最后一个不需要等待 + if i < len(pending_accounts) - 1: + time.sleep(stagger_delay) # 收集结果 for future in as_completed(future_to_account):