返回提交历史
Modified
g4f/Provider/Perchance.py
+3
-0
Modified
g4f/requests/cdp.py
+68
-0
XFEstudio/gpt4free
feat: enhance CDPSession with advanced Turnstile bypass mechanisms
bb8e8cb1
代码差异
2 个文件
+71
-0
@@ -62,6 +62,9 @@ class Perchance(AsyncGeneratorProvider, ProviderModelMixin):
62
62
"""
63
63
await session.evaluate_js(verify_js)
64
64
65
# Anti-detect: warm up the browser and disable debugger overhead DURING Turnstile check
66
await session.bypass_turnstile()
67
65
68
# Poll for userKey-0
66
69
user_key = None
67
70
for _ in range(30):
@@ -319,6 +319,27 @@ class CDPSession:
319
319
await self.call("Network.enable")
320
320
await self.call("Emulation.setFocusEmulationEnabled", enabled=True)
321
321
322
# Anti-detect: Override User-Agent to remove "HeadlessChrome"
323
user_agent = await self.evaluate_js("navigator.userAgent")
324
if user_agent and "HeadlessChrome" in user_agent:
325
clean_ua = user_agent.replace("HeadlessChrome", "Chrome")
326
await self.call("Network.setUserAgentOverride", userAgent=clean_ua)
327
328
# Anti-detect: Inject Stealth Script
329
stealth_js = """
330
Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
331
window.chrome = { runtime: {} };
332
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3] });
333
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] });
334
const originalGetParameter = WebGLRenderingContext.prototype.getParameter;
335
WebGLRenderingContext.prototype.getParameter = function(parameter) {
336
if (parameter === 37445) return 'Intel Inc.';
337
if (parameter === 37446) return 'Intel Iris OpenGL Engine';
338
return originalGetParameter.call(this, parameter);
339
};
340
"""
341
await self.call("Page.addScriptToEvaluateOnNewDocument", source=stealth_js)
342
322
343
async def _receiver_loop(self):
323
344
"""Listen for WebSocket messages."""
324
345
try:
@@ -464,6 +485,53 @@ class CDPSession:
464
485
self._event_handlers["Page.loadEventFired"].remove(fut)
465
486
logger.warning(f"Timeout waiting for Page.loadEventFired when navigating to {url}")
466
487
488
async def mouse_move(self, x: int, y: int):
489
"""Simulate a mouse movement to the given coordinates."""
490
await self.call("Input.dispatchMouseEvent", type="mouseMoved", x=x, y=y)
491
492
async def click(self, x: int, y: int, delay: float = 0.05):
493
"""Simulate a realistic mouse click at the given coordinates."""
494
await self.mouse_move(x, y)
495
await asyncio.sleep(0.02)
496
await self.call("Input.dispatchMouseEvent", type="mousePressed", button="left", clickCount=1, x=x, y=y)
497
await asyncio.sleep(delay)
498
await self.call("Input.dispatchMouseEvent", type="mouseReleased", button="left", clickCount=1, x=x, y=y)
499
500
async def bypass_turnstile(self):
501
"""Execute a sequence of anti-detect actions to bypass Cloudflare Turnstile."""
502
import random
503
# 1. Force the tab to be active
504
if self.target_id:
505
try:
506
await self.call("Target.activateTarget", targetId=self.target_id)
507
except Exception:
508
pass
509
510
# 2. Simulate realistic mouse movements
511
start_x, start_y = random.randint(10, 50), random.randint(10, 50)
512
end_x, end_y = random.randint(300, 600), random.randint(200, 500)
513
514
steps = 5
515
for i in range(steps):
516
x = start_x + (end_x - start_x) * (i / steps) + random.randint(-5, 5)
517
y = start_y + (end_y - start_y) * (i / steps) + random.randint(-5, 5)
518
await self.mouse_move(int(x), int(y))
519
await asyncio.sleep(random.uniform(0.05, 0.1))
520
521
# 3. Click randomly to gain focus
522
await self.click(end_x, end_y)
523
524
# 4. Scroll down slightly
525
await self.evaluate_js(f"window.scrollBy(0, {random.randint(100, 300)})")
526
await asyncio.sleep(0.2)
527
528
# 5. Temporarily disable Network interception to hide debugger overhead
529
try:
530
await self.call("Network.disable")
531
await asyncio.sleep(2)
532
finally:
533
await self.call("Network.enable")
534
467
535
async def close(self):
468
536
"""Close WebSocket session and close the specific target tab."""
469
537
self._closing = True