From ce68d2727cc0dffcb2dd769accaa97f2127a0bf1 Mon Sep 17 00:00:00 2001 From: protokey Date: Fri, 18 Sep 2026 16:21:07 +0400 Subject: [PATCH] =?UTF-8?q?chore:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8C=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B0?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D1=8C=20=D0=BB=D0=BE=D0=BA=D0=B0=D1=82=D0=BE?= =?UTF-8?q?=D1=80=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80?= =?UTF-8?q?=D0=B0=20=D1=8D=D0=BB=D0=B5=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=20?= =?UTF-8?q?=D1=81=D0=B8=D0=B3=D0=BD=D0=B0=D0=BB=D0=B8=D0=B7=D0=B8=D1=80?= =?UTF-8?q?=D1=83=D1=8E=D1=89=D0=B5=D0=B3=D0=BE=20=D0=BE=20=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=B8=D1=86=D0=B5=20=D0=B0=D0=BD=D1=82=D0=B8?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=20=D0=B7=D0=B0=D1=89=D0=B8=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/antibot/base.py | 6 +++++- src/antibot/known_providers/recaptcha.py | 2 +- src/antibot/orchestrator.py | 12 ++++++++++-- src/captcha/__init__.py | 1 + src/engine/actions.py | 21 +++++++++++++++------ src/engine/schemas.py | 1 + src/main.py | 4 +++- 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/antibot/base.py b/src/antibot/base.py index 52d557d..be54198 100644 --- a/src/antibot/base.py +++ b/src/antibot/base.py @@ -26,6 +26,7 @@ class ChallengeInfo: provider: str # "cloudflare_turnstile", "datadome", "hcaptcha", "recaptcha_v2", ... success: bool = False success_locator: str | None = None # локатор на странице за защитой + detect_locator: str | None = None # локатор на странице за защитой site_key: str | None = None # для стадии C, чтобы передать в 2captcha meta: dict | None = None # что-то специфичное для провайдера @@ -55,6 +56,7 @@ class AntiBotProvider: _solver_cls: Type[Solver] _detector_cls: Type[Detector] _success_locator: str | None = None + _detect_locator: str | None = None def __init__(self): self.detector = self._detector_cls() @@ -64,6 +66,7 @@ class AntiBotProvider: stage = Stage.INTERSTITIAL, provider = self.provider, success_locator = self._success_locator, + detect_locator = self._detect_locator, ) # обновление info await self.detector.detect(page, info) @@ -72,9 +75,10 @@ class AntiBotProvider: async def solve(self, page: Page, info: ChallengeInfo): await self.solver.solve(page, info) - def configure(self, success_locator=None, **kwargs): + def configure(self, success_locator=None, detect_locator=None, **kwargs): self.solver = self._solver_cls(**kwargs) self._success_locator = success_locator + self._detect_locator = detect_locator def clear(self): del self.solver diff --git a/src/antibot/known_providers/recaptcha.py b/src/antibot/known_providers/recaptcha.py index b8ec1e4..65f9b27 100644 --- a/src/antibot/known_providers/recaptcha.py +++ b/src/antibot/known_providers/recaptcha.py @@ -42,7 +42,7 @@ class ReCaptchaDetector(Detector): interactive_marker_selector = "body > div:nth-child(2) > div:nth-child(4) > iframe:nth-child(1)" # попытка определить что мы вообще на странице блокировки - marker_selector = "#captcha-form" + marker_selector = info.detect_locator or "#captcha-form" if not await page.query_selector(marker_selector): log.debug("Page is not a challenge form") if info.success_locator: diff --git a/src/antibot/orchestrator.py b/src/antibot/orchestrator.py index 8ace716..51388bd 100644 --- a/src/antibot/orchestrator.py +++ b/src/antibot/orchestrator.py @@ -25,7 +25,11 @@ class ChallengeOutcome: async def pass_challenges( - antibot_name, page, *, captcha=None, success_locator: str | None = None, timeout_ms=120_000) -> ChallengeOutcome: + antibot_name, page, *, + captcha=None, + success_locator: str | None = None, + detect_locator: str | None = None, + timeout_ms=120_000) -> ChallengeOutcome: # установка дедлайна deadline = time.monotonic() + timeout_ms / 1000 @@ -36,7 +40,11 @@ async def pass_challenges( else: captcha_solver = None provider = await select_one( - page, antibot_name, captcha_solver=captcha_solver, success_locator=success_locator) + page, antibot_name, + captcha_solver=captcha_solver, + success_locator=success_locator, + detect_locator=detect_locator, + ) except ProviderNotDetected: return ChallengeOutcome(False, None, None, "Provider not detected") diff --git a/src/captcha/__init__.py b/src/captcha/__init__.py index 5c7c30b..03766fb 100644 --- a/src/captcha/__init__.py +++ b/src/captcha/__init__.py @@ -1,2 +1,3 @@ from .hcaptcha import SolverHCaptcha +from .recaptcha import SolverReCaptcha from .base import load_captcha diff --git a/src/engine/actions.py b/src/engine/actions.py index 0281319..7e74189 100644 --- a/src/engine/actions.py +++ b/src/engine/actions.py @@ -65,28 +65,37 @@ async def wait_for(page: Page, act: ActionRequest, **kwargs) -> str | None: @register -async def pass_challenge(page: Page, act: ActionRequest, *, antibot_name, success_locator = None, captcha_key= None, **kwargs) -> str | None: - assert act.selector +async def pass_challenge( + page: Page, act: ActionRequest, *, + antibot_name, success_locator=None, captcha_key=None, detect_locator=None, + **kwargs +) -> str | None: await pass_challenges( antibot_name, page, - captcha=captcha_key, success_locator=act.selector + captcha=captcha_key, + success_locator=act.selector or success_locator, + detect_locator=detect_locator ) async def execute( page: Page, actions: list[ActionRequest], captcha_key: str | None = None, antibot_name: str | None = None, - success_locator: str | None = None) -> list[dict]: + success_locator: str | None = None, + detect_locator: str | None = None) -> list[dict]: """Выполнение очереди автоматизации""" actions_result = [] ctx = { "captcha_key": captcha_key, "antibot_name": antibot_name, - "success_locator": success_locator + "success_locator": success_locator, + "detect_locator": detect_locator, } await pass_challenges( antibot_name, page, - captcha=captcha, success_locator=success_locator + captcha=captcha_key, + success_locator=success_locator, + detect_locator=detect_locator, ) for act in actions: new_line = { diff --git a/src/engine/schemas.py b/src/engine/schemas.py index 83ccf51..66d1889 100644 --- a/src/engine/schemas.py +++ b/src/engine/schemas.py @@ -32,5 +32,6 @@ class SolveRequest(BaseModel): # TODO: screenshot: bool = False captcha: str | None = None + captcha_detect_locator: str | None = None captcha_success_locator: str | None = None captcha_type: str | None = None diff --git a/src/main.py b/src/main.py index 3b138b3..f5d997f 100644 --- a/src/main.py +++ b/src/main.py @@ -130,7 +130,9 @@ async def solve( actions_result = await actions.execute( page, payload.actions, payload.captcha, - antibot_name=payload.captcha_type, success_locator=payload.captcha_success_locator + antibot_name=payload.captcha_type, + success_locator=payload.captcha_success_locator, + detect_locator=payload.captcha_detect_locator, ) status = not "error" in actions_result[-1]