From 1fe0ebfea412200c9a0bb7402d7c734416a36097 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 17 Dec 2024 00:52:12 +0300 Subject: [PATCH] Update recaptcha_v2.py --- .../ReCaptchaV3TaskProxyless.py | 179 ------------- src/python3_anticaptcha/recaptcha_v2.py | 244 ++++++++++++++++++ 2 files changed, 244 insertions(+), 179 deletions(-) delete mode 100644 src/python3_anticaptcha/ReCaptchaV3TaskProxyless.py create mode 100644 src/python3_anticaptcha/recaptcha_v2.py diff --git a/src/python3_anticaptcha/ReCaptchaV3TaskProxyless.py b/src/python3_anticaptcha/ReCaptchaV3TaskProxyless.py deleted file mode 100644 index e21d9a0..0000000 --- a/src/python3_anticaptcha/ReCaptchaV3TaskProxyless.py +++ /dev/null @@ -1,179 +0,0 @@ -import time -import asyncio - -import aiohttp -import requests - -from python3_anticaptcha import app_key, create_task_url, get_sync_result, get_async_result - -MIN_SCORES = (0.3, 0.7, 0.9) - - -class ReCaptchaV3TaskProxyless: - def __init__(self, anticaptcha_key: str, sleep_time: int = 5, callbackUrl: str = None, **kwargs): - """ - Модуль отвечает за решение ReCaptcha v3 без прокси - :param anticaptcha_key: Ключ антикапчи - :param sleep_time: Время ожидания решения капчи - :param callbackUrl: URL для решения капчи с ответом через callback - :param kwargs: Другие необязательные параметры из документации - """ - if sleep_time < 5: - raise ValueError(f"Param `sleep_time` must be less than 5. U send - {sleep_time}") - self.sleep_time = sleep_time - - # Пайлоад для создания задачи - self.task_payload = { - "clientKey": anticaptcha_key, - "task": {"type": "RecaptchaV3TaskProxyless"}, - "softId": app_key, - } - # задаём callbackUrl если передан - if callbackUrl: - self.task_payload.update({"callbackUrl": callbackUrl}) - - # Пайлоад для получения результата - self.result_payload = {"clientKey": anticaptcha_key} - - # Если переданы ещё параметры - вносим их в payload - if kwargs: - for key in kwargs: - self.task_payload["task"].update({key: kwargs[key]}) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - if exc_type: - return False - return True - - # Работа с капчёй - def captcha_handler( - self, websiteURL: str, websiteKey: str, minScore: float, pageAction: str = None, **kwargs - ) -> dict: - """ - Метод решения ReCaptcha V3 - :param websiteURL: Ссылка на страницу с капчёй - :param websiteKey: Ключ-индентификатор рекапчи на целевой странице. Берется из HTML этой страницы. - :param minScore: Определяет фильтр, по которому отбирается работник с нужным минимальным score. - :param pageAction: Значение параметра action, которое передается виджетом рекапчи в гугл, - и которое потом видит владелец сайта при проверке токена. - :param kwargs: Дополнительные параметры для `requests.post(....)`, который отправляет даныйе на решение. - :return: Возвращает ответ сервера в виде JSON-строки - """ - if minScore not in MIN_SCORES: - raise ValueError(f"Wrong `minScore` param - {minScore}, available params - {MIN_SCORES};") - # вставляем в пайлоад адрес страницы и ключ-индентификатор рекапчи - self.task_payload["task"].update( - { - "websiteURL": websiteURL, - "websiteKey": websiteKey, - "minScore": minScore, - "pageAction": pageAction, - } - ) - # Отправляем на антикапчу пайлоад - # в результате получаем JSON ответ содержащий номер решаемой капчи - captcha_id = requests.post(create_task_url, json=self.task_payload, verify=False, **kwargs).json() - - # Проверка статуса создания задачи, если создано без ошибок - извлекаем ID задачи, иначе возвращаем ответ сервера - if captcha_id["errorId"] == 0: - captcha_id = captcha_id["taskId"] - self.result_payload.update({"taskId": captcha_id}) - else: - return captcha_id - - # если передан параметр `callbackUrl` - не ждём решения капчи а возвращаем незаполненный ответ - if self.task_payload.get("callbackUrl"): - return self.result_payload - - else: - # Ожидаем решения капчи - time.sleep(self.sleep_time) - return get_sync_result(result_payload=self.result_payload, sleep_time=self.sleep_time, **kwargs) - - -class aioReCaptchaV3TaskProxyless: - def __init__(self, anticaptcha_key: str, sleep_time: int = 5, callbackUrl: str = None, **kwargs): - """ - Модуль отвечает за решение ReCaptcha V3 без прокси - :param anticaptcha_key: Ключ антикапчи - :param sleep_time: Время ожидания решения капчи - :param callbackUrl: URL для решения капчи с ответом через callback - :param kwargs: Другие необязательные параметры из документации - """ - if sleep_time < 5: - raise ValueError(f"Param `sleep_time` must be less than 5. U send - {sleep_time}") - self.sleep_time = sleep_time - - # Пайлоад для создания задачи - self.task_payload = { - "clientKey": anticaptcha_key, - "task": {"type": "RecaptchaV3TaskProxyless"}, - "softId": app_key, - } - - # задаём callbackUrl если передан - if callbackUrl: - self.task_payload.update({"callbackUrl": callbackUrl}) - - # Пайлоад для получения результата - self.result_payload = {"clientKey": anticaptcha_key} - - # Если переданы ещё параметры - вносим их в payload - if kwargs: - for key in kwargs: - self.task_payload["task"].update({key: kwargs[key]}) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - if exc_type: - return False - return True - - # Работа с капчёй - async def captcha_handler(self, websiteURL: str, websiteKey: str, minScore: float, pageAction: str = None) -> dict: - """ - Метод решения ReCaptcha V3 - :param websiteURL: Ссылка на страницу с капчёй - :param websiteKey: Ключ-индентификатор рекапчи на целевой странице. Берется из HTML этой страницы. - :param minScore: Определяет фильтр, по которому отбирается работник с нужным минимальным score. - :param pageAction: Значение параметра action, которое передается виджетом рекапчи в гугл, - и которое потом видит владелец сайта при проверке токена. - :return: Возвращает ответ сервера в виде JSON-строки - """ - if minScore not in MIN_SCORES: - raise ValueError(f"Wrong `minScore` param - {minScore}, available params - {MIN_SCORES};") - # вставляем в пайлоад адрес страницы и ключ-индентификатор рекапчи - self.task_payload["task"].update( - { - "websiteURL": websiteURL, - "websiteKey": websiteKey, - "minScore": minScore, - "pageAction": pageAction, - } - ) - # Отправляем на антикапчу пайлоад - # в результате получаем JSON ответ содержащий номер решаемой капчи - async with aiohttp.ClientSession() as session: - async with session.post(create_task_url, json=self.task_payload) as resp: - captcha_id = await resp.json() - - # Проверка статуса создания задачи, если создано без ошибок - извлекаем ID задачи, иначе возвращаем ответ сервера - if captcha_id["errorId"] == 0: - captcha_id = captcha_id["taskId"] - self.result_payload.update({"taskId": captcha_id}) - else: - return captcha_id - - # если передан параметр `callbackUrl` - не ждём решения капчи а возвращаем незаполненный ответ - if self.task_payload.get("callbackUrl"): - return self.result_payload - - else: - # Ждем решения капчи - await asyncio.sleep(self.sleep_time) - return await get_async_result(result_payload=self.result_payload, sleep_time=self.sleep_time) diff --git a/src/python3_anticaptcha/recaptcha_v2.py b/src/python3_anticaptcha/recaptcha_v2.py new file mode 100644 index 0000000..1a3bef3 --- /dev/null +++ b/src/python3_anticaptcha/recaptcha_v2.py @@ -0,0 +1,244 @@ +from typing import Union, Optional + +from .core.base import CaptchaParams +from .core.enum import ProxyTypeEnm, CaptchaTypeEnm +from .core.aio_captcha_handler import AIOCaptchaHandler +from .core.sio_captcha_handler import SIOCaptchaHandler + +MIN_SCORES = (0.3, 0.7, 0.9) + + +class ReCaptchaV2(CaptchaParams): + def __init__( + self, + api_key: str, + captcha_type: Union[CaptchaTypeEnm, str], + websiteURL: str, + websiteKey: str, + recaptchaDataSValue: Optional[str] = None, + isInvisible: bool = False, + enterprisePayload: Optional[dict] = None, + apiDomain: Optional[str] = None, + initParameters: Optional[str] = None, + proxyType: Optional[Union[ProxyTypeEnm, str]] = None, + proxyAddress: Optional[str] = None, + proxyPort: Optional[int] = None, + proxyLogin: Optional[str] = None, + proxyPassword: Optional[str] = None, + userAgent: Optional[str] = None, + cookies: Optional[str] = None, + sleep_time: int = 10, + ): + """ + The class is used to work with ReCaptchaV2 and RecaptchaV2Enterprise. + + Args: + api_key: Capsolver API key + captcha_type: Captcha type + websiteURL: Address of the webpage + websiteKey: Recaptcha website key. + recaptchaDataSValue: Value of 'data-s' parameter. + Applies only to reCaptchas on Google web sites. + isInvisible: Specify whether or not reCaptcha is invisible. + This will render an appropriate widget for our workers. + enterprisePayload: Additional parameters which should be passed to + "grecaptcha.enterprise.render" method along with sitekey. + apiDomain: Use this parameter to send the domain name from which the reCaptcha script should be served. + Can have only one of two values: "www.google.com" or "www.recaptcha.net". + Do not use this parameter unless you understand what you are doing. + proxyType: Type of the proxy + proxyAddress: Proxy IP address IPv4/IPv6. Not allowed to use: + host names instead of IPs, + transparent proxies (where client IP is visible), + proxies from local networks (192.., 10.., 127...) + proxyPort: Proxy port. + proxyLogin: Proxy login. + proxyPassword: Proxy password. + userAgent: Browser UserAgent. + cookies: Additional cookies that we should use in Google domains. + sleep_time: The waiting time between requests to get the result of the Captcha + + Examples: + >>> ReCaptchaV2(api_key="99d7d111a0111dc11184111c8bb111da", + ... captcha_type=CaptchaTypeEnm.RecaptchaV2TaskProxyless, + ... websiteURL="https://www.geetest.com/en/adaptive-captcha-demo", + ... websiteKey="6Lc_aCMTAAAAABx7u2N0D1XnVbI_v6ZdbM6rYf16", + ... recaptchaDataSValue="12345678abc90123d45678ef90123a456b", + ... isInvisible=False, + ... ).captcha_handler() + { + "errorId": 0, + "errorCode": None, + "errorDescription": None, + "status":"ready", + "solution":{ + "gRecaptchaResponse":"3AHJ_VuvYIB.......6a3" + }, + "cost": 0.002, + "ip": "46.53.249.230", + "createTime": 1679004358, + "endTime": 1679004368, + "solveCount": 0, + "taskId": 396687629 + } + + >>> await ReCaptchaV2(api_key="99d7d111a0111dc11184111c8bb111da", + ... captcha_type=CaptchaTypeEnm.RecaptchaV2Task, + ... websiteURL="https://www.geetest.com/en/adaptive-captcha-demo", + ... websiteKey="6Lc_aCMTAAAAABx7u2N0D1XnVbI_v6ZdbM6rYf16", + ... recaptchaDataSValue="12345678abc90123d45678ef90123a456b", + ... isInvisible=False, + ... proxyType="http", + ... proxyAddress="0.0.0.0", + ... proxyPort=9988, + ... proxyLogin="proxy_login", + ... proxyPassword="proxy_password", + ... userAgent="some_real_user_agent", + ... cookies="some-cookies-data", + ... ).aio_captcha_handler() + { + "errorId": 0, + "errorCode": None, + "errorDescription": None, + "status":"ready", + "solution":{ + "gRecaptchaResponse":"3AHJ_VuvYIB.......6a3" + }, + "cost": 0.002, + "ip": "46.53.249.230", + "createTime": 1679004358, + "endTime": 1679004368, + "solveCount": 0, + "taskId": 396687629 + } + + >>> ReCaptchaV2(api_key="99d7d111a0111dc11184111c8bb111da", + ... captcha_type=CaptchaTypeEnm.RecaptchaV2EnterpriseTaskProxyless, + ... websiteURL="https://www.geetest.com/en/adaptive-captcha-demo", + ... websiteKey="6Lc_aCMTAAAAABx7u2N0D1XnVbI_v6ZdbM6rYf16", + ... enterprisePayload={ + ... "s": "SOME_ADDITIONAL_TOKEN" + ... }, + ... apiDomain="www.google.com", + ... ).captcha_handler() + { + "errorId": 0, + "errorCode": None, + "errorDescription": None, + "status":"ready", + "solution":{ + "gRecaptchaResponse":"3AHJ_VuvYIB.......6a3" + }, + "cost": 0.002, + "ip": "46.53.249.230", + "createTime": 1679004358, + "endTime": 1679004368, + "solveCount": 0, + "taskId": 396687629 + } + + Notes: + https://anti-captcha.com/apidoc/task-types/RecaptchaV2TaskProxyless + + https://anti-captcha.com/apidoc/task-types/RecaptchaV2Task + + https://anti-captcha.com/apidoc/task-types/RecaptchaV2EnterpriseTaskProxyless + + https://anti-captcha.com/apidoc/task-types/RecaptchaV2EnterpriseTask + """ + super().__init__(api_key=api_key, sleep_time=sleep_time) + self.task_params = dict( + type=captcha_type, + websiteURL=websiteURL, + websiteKey=websiteKey, + ) + if captcha_type in ( + CaptchaTypeEnm.RecaptchaV2TaskProxyless, + CaptchaTypeEnm.RecaptchaV2Task, + ): + self.task_params.update( + dict( + recaptchaDataSValue=recaptchaDataSValue, + isInvisible=isInvisible, + ) + ) + if captcha_type == CaptchaTypeEnm.RecaptchaV2Task: + self.task_params.update( + dict( + proxyType=proxyType, + proxyAddress=proxyAddress, + proxyPort=proxyPort, + proxyLogin=proxyLogin, + proxyPassword=proxyPassword, + userAgent=userAgent, + cookies=cookies, + ) + ) + elif captcha_type in ( + CaptchaTypeEnm.RecaptchaV2EnterpriseTask, + CaptchaTypeEnm.RecaptchaV2EnterpriseTaskProxyless, + ): + self.task_params.update( + dict( + enterprisePayload=enterprisePayload, + apiDomain=apiDomain, + ) + ) + if captcha_type == CaptchaTypeEnm.RecaptchaV2EnterpriseTask: + self.task_params.update( + dict( + proxyType=proxyType, + proxyAddress=proxyAddress, + proxyPort=proxyPort, + proxyLogin=proxyLogin, + proxyPassword=proxyPassword, + userAgent=userAgent, + cookies=cookies, + ) + ) + else: + raise ValueError( + f"Invalid `captcha_type` parameter set for `{self.__class__.__name__}`, \ + available - {CaptchaTypeEnm.RecaptchaV2Task.value, + CaptchaTypeEnm.RecaptchaV2TaskProxyless.value, + CaptchaTypeEnm.RecaptchaV2EnterpriseTask.value, + CaptchaTypeEnm.RecaptchaV2EnterpriseTaskProxyless.value}" + ) + + def captcha_handler(self, **additional_params) -> dict: + """ + Synchronous method for captcha solving + + Args: + additional_params: Some additional parameters that will be used in creating the task + and will be passed to the payload under ``task`` key. + Like ``proxyLogin``, ``proxyPassword`` and etc. - more info in service docs + + Returns: + Dict with full server response + + Notes: + Check class docstirng for more info + """ + self.task_params.update({**additional_params}) + self._captcha_handling_instrument = SIOCaptchaHandler(captcha_params=self) + return self._captcha_handling_instrument.processing_captcha() + + async def aio_captcha_handler(self, **additional_params) -> dict: + """ + Asynchronous method for captcha solving + + Args: + additional_params: Some additional parameters that will be used in creating the task + and will be passed to the payload under ``task`` key. + Like ``proxyLogin``, ``proxyPassword`` and etc. - more info in service docs + + Returns: + Dict with full server response + + Notes: + Check class docstirng for more info + """ + self.task_params.update({**additional_params}) + self._captcha_handling_instrument = AIOCaptchaHandler(captcha_params=self) + return await self._captcha_handling_instrument.processing_captcha()