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 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 playwright.async_api import Page
|
||||||
|
|
||||||
from ..base import Detector, ChallengeInfo
|
from ..base import Detector, ChallengeInfo, AntiBotProvider, Solver
|
||||||
from ..base import Stage
|
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):
|
class CloudflareDetector(Detector):
|
||||||
provider = 'cloudflare_turnstile'
|
|
||||||
stage = Stage.INTERSTITIAL
|
|
||||||
|
|
||||||
async def detect(self, page: Page) -> ChallengeInfo:
|
async def detect(self, page: Page, info: ChallengeInfo):
|
||||||
result = ChallengeInfo(
|
log.debug("CloudflareDetector run")
|
||||||
stage=self.stage,
|
info.meta = {}
|
||||||
provider=self.provider,
|
checkbox_selector = "иногда надо тыкнуть, сейчас этого нет"
|
||||||
)
|
marker_selector = info.detect_locator or "//input[@name='cf-turnstile-response']"
|
||||||
# TODO: добавить функцию определения что страница с проверкой показана
|
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
|
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