fix: reCAPTCHA — закрытие окна с картинками и вызов callback (#10)
- Окно с картинками закрывается кликом в угол подложки: в её центре лежит само окно и перехватывает клик (Locator.click падал по таймауту 60 с). - form_submit выполняется в основном мире страницы (isolated_context=False): префикс "mw:" patchright не поддерживает, в изолированном мире ___grecaptcha_cfg не виден — "Recaptcha callback function not found". - Воркер: LOG_LEVEL выставляется корневому логгеру явно — dramatiq настраивает логирование раньше, и basicConfig ничего не делал. make dev — LOG_LEVEL=DEBUG. - test_main.http: запрос на zennolab с проверкой результата по #main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4d90dc4a21
commit
0e10fb671d
5 files changed
+19
-13
No files matched your search
@@ -33,7 +33,8 @@ export DEV_RABBITMQ_PORT DEV_REDIS_PORT DEV_POSTGRES_PORT RABBITMQ_PASSWORD POST
|
||||
DEV_ENV := RABBITMQ_URL=amqp://robotex:$(RABBITMQ_PASSWORD)@localhost:$(DEV_RABBITMQ_PORT)/ \
|
||||
REDIS_URL=redis://localhost:$(DEV_REDIS_PORT)/0 \
|
||||
DATABASE_URL=postgresql+asyncpg://robotex:$(POSTGRES_PASSWORD)@localhost:$(DEV_POSTGRES_PORT)/robotex \
|
||||
BROWSER_SLOTS=$(DEV_SLOTS)
|
||||
BROWSER_SLOTS=$(DEV_SLOTS) \
|
||||
LOG_LEVEL=DEBUG
|
||||
|
||||
help:
|
||||
@echo "make install <pkg> [<pkg> ...] - установить пакет(ы) в $(VENV), обновить $(REQUIREMENTS), собрать wheel в $(WHEELS_DIR)/"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from patchright.async_api import Page
|
||||
@@ -6,7 +5,7 @@ from patchright.async_api import Page
|
||||
from captcha.base import Captcha
|
||||
|
||||
from ..base import Detector, ChallengeInfo, Solver, AntiBotProvider, click_and_race
|
||||
from ..base import Stage
|
||||
from ..base import Stage, PWTimeoutError
|
||||
from ..registry import register
|
||||
from ..exceptions import IframeLoadError
|
||||
|
||||
@@ -56,8 +55,8 @@ class ReCaptchaSolver(Solver):
|
||||
self.captcha_solver: Captcha = self._opt["captcha_solver"]
|
||||
|
||||
async def form_submit(self, token: str) -> bool:
|
||||
# noinspection UnnecessaryLabelJS
|
||||
return await self.page.evaluate(f"mw:({JS_CHALLENGE_SUBMIT})({json.dumps(token)})")
|
||||
# ___grecaptcha_cfg живёт в основном мире страницы, а patchright по умолчанию выполняет скрипт в изолированном
|
||||
return await self.page.evaluate(JS_CHALLENGE_SUBMIT, token, isolated_context=False)
|
||||
|
||||
async def solve(self, page: Page, info: ChallengeInfo):
|
||||
self.page = page
|
||||
@@ -76,9 +75,15 @@ class ReCaptchaSolver(Solver):
|
||||
return
|
||||
else:
|
||||
log.debug("Нужно решать капчу. Закрою окошко с картинками.")
|
||||
# полупрозрачная подложка на весь экран (position: fixed), клик по ней закрывает окно. В её центре лежит
|
||||
# само окно с картинками и перехватывает клик — поэтому кликаем в угол
|
||||
element = page.locator("xpath=//div[@class='g-recaptcha-bubble-arrow']/../div[1]")
|
||||
if await element.is_visible():
|
||||
await element.click()
|
||||
try:
|
||||
await element.click(position={"x": 1, "y": 1}, timeout=5_000)
|
||||
except PWTimeoutError:
|
||||
# не закрылось — не страшно, токен уходит через callback
|
||||
log.debug("Окошко с картинками закрыть не удалось")
|
||||
|
||||
log.debug("Решаем капчу...")
|
||||
assert info.detect_locator
|
||||
|
||||
@@ -30,6 +30,7 @@ class Captcha:
|
||||
return resp
|
||||
|
||||
async def turnstile(self, url, site_key):
|
||||
# TODO: not finished!
|
||||
resp = await self._run(self._solver.turnstile, site_key, url)
|
||||
return resp
|
||||
|
||||
|
||||
@@ -10,10 +10,13 @@ import logging
|
||||
import os
|
||||
import socket
|
||||
|
||||
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
|
||||
logging.basicConfig(
|
||||
level=os.getenv("LOG_LEVEL", "INFO").upper(),
|
||||
level=LOG_LEVEL,
|
||||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||||
)
|
||||
# под dramatiq логирование уже настроено им самим (уровень INFO) и basicConfig ничего не делает — уровень явно
|
||||
logging.getLogger().setLevel(LOG_LEVEL)
|
||||
|
||||
import dramatiq # noqa: E402
|
||||
from dramatiq.asyncio import get_event_loop_thread # noqa: E402
|
||||
|
||||
@@ -147,18 +147,14 @@ X-API-Key: {{api_key}}
|
||||
"url": "https://lessons.zennolab.com/captchas/recaptcha/v2_nosubmit.php?level=low",
|
||||
"proxy": "{{proxy}}",
|
||||
"actions": [
|
||||
{
|
||||
"type": "pass_challenge",
|
||||
"value": "recaptcha"
|
||||
},
|
||||
{
|
||||
"type": "inner_text",
|
||||
"selector": "//button[contains(@class, 'actionItem_151') and @type='submit']"
|
||||
"selector": "//div[@id='main']/div/h2"
|
||||
}
|
||||
],
|
||||
"captcha": "{{captcha_key}}",
|
||||
"captcha_type": "recaptcha",
|
||||
"captcha_success_locator": "//code[contains(@class, 'hljs _successMessageCode')]"
|
||||
"captcha_success_locator": "//div[@id='main']"
|
||||
}
|
||||
|
||||
###
|
||||
Reference in new issue
Block a user