feature: добавлена реализация antibot для cloudflare

This commit is contained in:
protokey committed 2026-09-22 13:49:30 +04:00
1 parent a0170c9754
commit 5146f74e43
2 files changed
+128 -13

No files matched your search

+127 -13
View File
@@ -1,20 +1,134 @@
"""
<input type="hidden" name="cf-turnstile-response" id="cf-chl-widget-kda53_response">
<div class="footer" role="contentinfo">
<div class="footer-inner">
<div class="footer-wrapper">
<div>
<div class="ray-id">Ray ID: <code>a3ea73c2a817983b</code>
</div>
</div>
<div class="footer-link-wrapper">
<span class="footer-text">Производительность и безопасность с <a rel="noopener noreferrer" href="https://www.cloudflare.com?utm_source=challenge&amp;utm_campaign=m" target="_blank" aria-label="Cloudflare, открывается в новой вкладке">Cloudflare</a>
</span>
<span class="footer-divider"></span>
<a target="_blank" rel="noopener noreferrer" href="https://www.cloudflare.com/privacypolicy/" aria-label="Конфиденциальность, открывается в новой вкладке" class="footer-text">Конфиденциальность</a>
</div>
</div>
</div>
</div>
//input[@name="cf-turnstile-response"]
//footer/footer-inner/footer-wrapper/div[@class="ray-id"]
iFrame with checkbox
<div class="main-wrapper RUWFy0" role="main">
<div class="main-content">
<div class="lpdkQ3">
<img src="/favicon.ico" class="uMaz2" alt="Значок zkillboard.com">
<h1>zkillboard.com</h1>
</div>
<h2 id="jddkS1" class="YNaX0 MmgY4">Выполнение проверки безопасности</h2>
<p id="QeINV1" class="nnhvx2 ndZkd3">Этот веб-сайт использует сервис безопасности для защиты от вредоносных ботов. Эта страница отображается, пока веб-сайт проверяет, что вы не бот.</p>
<div id="lVJB5" style="display: grid;">
<div>
<div>
<div></div>
<input type="hidden" name="cf-turnstile-response" id="cf-chl-widget-2t1qg_response">
</div>
</div>
</div>
<div id="CJPCL0" style="display: none;">
<h2 id="zfpQF7" class="ndZkd3">Проверка выполнена успешно. Ожидание ответа zkillboard.com</h2>
</div>
<div id="EaAgR8" class="Wivzc8 aLvno9" style="display: none; visibility: hidden;">
<div class="TighH9">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<noscript>
<div class="h2">
<span id="challenge-error-text">Enable JavaScript and cookies to continue</span>
</div>
</noscript>
</div>
</div>
"""
import logging
import time
from playwright.async_api import Page
from ..base import Detector, ChallengeInfo
from ..base import Detector, ChallengeInfo, AntiBotProvider, Solver
from ..base import Stage
from ..registry import register_detector
from ..registry import register
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.addHandler(logging.StreamHandler())
@register_detector
class CloudflareDetector(Detector):
provider = 'cloudflare_turnstile'
stage = Stage.INTERSTITIAL
async def detect(self, page: Page) -> ChallengeInfo:
result = ChallengeInfo(
stage=self.stage,
provider=self.provider,
)
# TODO: добавить функцию определения что страница с проверкой показана
raise NotImplementedError
return result
async def detect(self, page: Page, info: ChallengeInfo):
log.debug("CloudflareDetector run")
info.meta = {}
checkbox_selector = "иногда надо тыкнуть, сейчас этого нет"
marker_selector = info.detect_locator or "//input[@name='cf-turnstile-response']"
info.detect_locator = marker_selector
log.debug(f"ищем {marker_selector} успех если есть {info.success_locator}")
if await page.locator(info.detect_locator).count() == 0:
log.debug("на странице нет маркера преграды")
if info.success_locator:
info.success = bool(await page.query_selector(info.success_locator))
info.meta["reason"] = [
"Нет маркера блокировки и нет маркера успеха :-(",
"Нет маркера блокировки зато есть маркер успеха :-)"
][info.success]
else:
info.success = True
info.meta["reason"] = "нет маркера блокировки"
log.debug("Решение не требуется")
return
info.stage = Stage.INTERSTITIAL
return
if await page.query_selector(checkbox_selector):
info.stage = Stage.CHECKBOX
else:
info.stage = Stage.INTERSTITIAL
class CloudflareSolver(Solver):
async def solve(self, page: Page, info: ChallengeInfo):
if info.stage == Stage.CHECKBOX:
raise NotImplementedError
elif info.stage == Stage.INTERSTITIAL:
if info.success_locator:
try:
await page.wait_for_selector(info.success_locator)
except Exception:
return
else:
return
else:
deadline = time.time() + 30
while time.time() < deadline:
if not await page.query_selector(info.detect_locator):
return
return
else:
raise NotImplementedError
@register
class ReCaptchaProvider(AntiBotProvider):
provider = 'cloudflare'
_solver_cls = CloudflareSolver
_detector_cls = CloudflareDetector