2
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
28
run.py
28
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):
|
||||
|
||||
Reference in New Issue
Block a user