feature: добавлена реализация antibot для cloudflare
This commit is contained in:
1 parent
a0170c9754
commit
5146f74e43
2 files changed
+127
-12
No files matched your search
@@ -1 +1,2 @@
|
||||
from .known_providers import recaptcha
|
||||
from .known_providers import cloudflare
|
||||
@@ -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&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: добавить функцию определения что страница с проверкой показана
|
||||
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
|
||||
return result
|
||||
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
|
||||
Reference in new issue
Block a user