Aggiornato cloudscraper
This commit is contained in:
@@ -54,7 +54,7 @@ except ImportError:
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
__version__ = '1.2.30'
|
__version__ = '1.2.32'
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
@@ -148,6 +148,15 @@ class CloudScraper(Session):
|
|||||||
def __getstate__(self):
|
def __getstate__(self):
|
||||||
return self.__dict__
|
return self.__dict__
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------- #
|
||||||
|
# Raise an Exception with no stacktrace and reset depth counter.
|
||||||
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
|
def simpleException(self, exception, msg):
|
||||||
|
self._solveDepthCnt = 0
|
||||||
|
sys.tracebacklimit = 0
|
||||||
|
raise exception(msg)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
# debug the request via the response
|
# debug the request via the response
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
@@ -219,9 +228,8 @@ class CloudScraper(Session):
|
|||||||
|
|
||||||
if self._solveDepthCnt >= self.solveDepth:
|
if self._solveDepthCnt >= self.solveDepth:
|
||||||
_ = self._solveDepthCnt
|
_ = self._solveDepthCnt
|
||||||
self._solveDepthCnt = 0
|
self.simpleException(
|
||||||
sys.tracebacklimit = 0
|
CloudflareLoopProtection,
|
||||||
raise CloudflareLoopProtection(
|
|
||||||
"!!Loop Protection!! We have tried to solve {} time(s) in a row.".format(_)
|
"!!Loop Protection!! We have tried to solve {} time(s) in a row.".format(_)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -303,8 +311,10 @@ class CloudScraper(Session):
|
|||||||
|
|
||||||
def is_Challenge_Request(self, resp):
|
def is_Challenge_Request(self, resp):
|
||||||
if self.is_Firewall_Blocked(resp):
|
if self.is_Firewall_Blocked(resp):
|
||||||
sys.tracebacklimit = 0
|
self.simpleException(
|
||||||
raise CloudflareCode1020('Cloudflare has blocked this request (Code 1020 Detected).')
|
CloudflareCode1020,
|
||||||
|
'Cloudflare has blocked this request (Code 1020 Detected).'
|
||||||
|
)
|
||||||
|
|
||||||
if self.is_reCaptcha_Challenge(resp) or self.is_IUAM_Challenge(resp):
|
if self.is_reCaptcha_Challenge(resp) or self.is_IUAM_Challenge(resp):
|
||||||
return True
|
return True
|
||||||
@@ -317,16 +327,29 @@ class CloudScraper(Session):
|
|||||||
|
|
||||||
def IUAM_Challenge_Response(self, body, url, interpreter):
|
def IUAM_Challenge_Response(self, body, url, interpreter):
|
||||||
try:
|
try:
|
||||||
challengeUUID = re.search(
|
formPayload = re.search(
|
||||||
r'id="challenge-form" action="(?P<challengeUUID>\S+)"',
|
r'<form (?P<form>id="challenge-form" action="(?P<challengeUUID>.*?'
|
||||||
body, re.M | re.DOTALL
|
r'__cf_chl_jschl_tk__=\S+)"(.*?)</form>)',
|
||||||
).groupdict().get('challengeUUID', '')
|
body,
|
||||||
|
re.M | re.DOTALL
|
||||||
|
).groupdict()
|
||||||
|
|
||||||
payload = OrderedDict(re.findall(r'name="(r|jschl_vc|pass)"\svalue="(.*?)"', body))
|
if not all(key in formPayload for key in ['form', 'challengeUUID']):
|
||||||
|
self.simpleException(
|
||||||
|
CloudflareIUAMError,
|
||||||
|
"Cloudflare IUAM detected, unfortunately we can't extract the parameters correctly."
|
||||||
|
)
|
||||||
|
|
||||||
|
payload = OrderedDict(
|
||||||
|
re.findall(
|
||||||
|
r'name="(r|jschl_vc|pass)"\svalue="(.*?)"',
|
||||||
|
formPayload['form']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
sys.tracebacklimit = 0
|
self.simpleException(
|
||||||
raise CloudflareIUAMError(
|
CloudflareIUAMError,
|
||||||
"Cloudflare IUAM detected, unfortunately we can't extract the parameters correctly."
|
"Cloudflare IUAM detected, unfortunately we can't extract the parameters correctly."
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -337,8 +360,8 @@ class CloudScraper(Session):
|
|||||||
interpreter
|
interpreter
|
||||||
).solveChallenge(body, hostParsed.netloc)
|
).solveChallenge(body, hostParsed.netloc)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.tracebacklimit = 0
|
self.simpleException(
|
||||||
raise CloudflareIUAMError(
|
CloudflareIUAMError,
|
||||||
'Unable to parse Cloudflare anti-bots page: {}'.format(
|
'Unable to parse Cloudflare anti-bots page: {}'.format(
|
||||||
getattr(e, 'message', e)
|
getattr(e, 'message', e)
|
||||||
)
|
)
|
||||||
@@ -348,7 +371,7 @@ class CloudScraper(Session):
|
|||||||
'url': '{}://{}{}'.format(
|
'url': '{}://{}{}'.format(
|
||||||
hostParsed.scheme,
|
hostParsed.scheme,
|
||||||
hostParsed.netloc,
|
hostParsed.netloc,
|
||||||
self.unescape(challengeUUID)
|
self.unescape(formPayload['challengeUUID'])
|
||||||
),
|
),
|
||||||
'data': payload
|
'data': payload
|
||||||
}
|
}
|
||||||
@@ -359,34 +382,62 @@ class CloudScraper(Session):
|
|||||||
|
|
||||||
def reCaptcha_Challenge_Response(self, provider, provider_params, body, url):
|
def reCaptcha_Challenge_Response(self, provider, provider_params, body, url):
|
||||||
try:
|
try:
|
||||||
payload = re.search(
|
formPayload = re.search(
|
||||||
r'(name="r"\svalue="(?P<r>\S+)"|).*?challenge-form" action="(?P<challengeUUID>\S+)".*?'
|
r'<form class="challenge-form" (?P<form>id="challenge-form" '
|
||||||
r'data-ray="(?P<data_ray>\S+)".*?data-sitekey="(?P<site_key>\S+)"',
|
r'action="(?P<challengeUUID>.*?__cf_chl_captcha_tk__=\S+)"(.*?)</form>)',
|
||||||
body, re.M | re.DOTALL
|
body,
|
||||||
|
re.M | re.DOTALL
|
||||||
).groupdict()
|
).groupdict()
|
||||||
except (AttributeError):
|
|
||||||
sys.tracebacklimit = 0
|
if not all(key in formPayload for key in ['form', 'challengeUUID']):
|
||||||
raise CloudflareReCaptchaError(
|
self.simpleException(
|
||||||
|
CloudflareReCaptchaError,
|
||||||
"Cloudflare reCaptcha detected, unfortunately we can't extract the parameters correctly."
|
"Cloudflare reCaptcha detected, unfortunately we can't extract the parameters correctly."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
payload = OrderedDict(
|
||||||
|
re.findall(
|
||||||
|
r'(name="r"\svalue|data-ray|data-sitekey|name="cf_captcha_kind"\svalue)="(.*?)"',
|
||||||
|
formPayload['form']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
captchaType = 'reCaptcha' if payload['name="cf_captcha_kind" value'] == 're' else 'hCaptcha'
|
||||||
|
|
||||||
|
except (AttributeError, KeyError):
|
||||||
|
self.simpleException(
|
||||||
|
CloudflareReCaptchaError,
|
||||||
|
"Cloudflare reCaptcha detected, unfortunately we can't extract the parameters correctly."
|
||||||
|
)
|
||||||
|
|
||||||
|
captchaResponse = reCaptcha.dynamicImport(
|
||||||
|
provider.lower()
|
||||||
|
).solveCaptcha(
|
||||||
|
captchaType,
|
||||||
|
url,
|
||||||
|
payload['data-sitekey'],
|
||||||
|
provider_params
|
||||||
|
)
|
||||||
|
|
||||||
|
dataPayload = OrderedDict([
|
||||||
|
('r', payload.get('name="r" value', '')),
|
||||||
|
('cf_captcha_kind', payload['name="cf_captcha_kind" value']),
|
||||||
|
('id', payload.get('data-ray')),
|
||||||
|
('g-recaptcha-response', captchaResponse)
|
||||||
|
])
|
||||||
|
|
||||||
|
if captchaType == 'hCaptcha':
|
||||||
|
dataPayload.update({'h-captcha-response': captchaResponse})
|
||||||
|
|
||||||
hostParsed = urlparse(url)
|
hostParsed = urlparse(url)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'url': '{}://{}{}'.format(
|
'url': '{}://{}{}'.format(
|
||||||
hostParsed.scheme,
|
hostParsed.scheme,
|
||||||
hostParsed.netloc,
|
hostParsed.netloc,
|
||||||
self.unescape(payload.get('challengeUUID', ''))
|
self.unescape(formPayload['challengeUUID'])
|
||||||
),
|
),
|
||||||
'data': OrderedDict([
|
'data': dataPayload
|
||||||
('r', payload.get('r', '')),
|
|
||||||
('id', payload.get('data_ray')),
|
|
||||||
(
|
|
||||||
'g-recaptcha-response',
|
|
||||||
reCaptcha.dynamicImport(
|
|
||||||
provider.lower()
|
|
||||||
).solveCaptcha(url, payload.get('site_key'), provider_params)
|
|
||||||
)
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
@@ -412,8 +463,8 @@ class CloudScraper(Session):
|
|||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
if not self.recaptcha or not isinstance(self.recaptcha, dict) or not self.recaptcha.get('provider'):
|
if not self.recaptcha or not isinstance(self.recaptcha, dict) or not self.recaptcha.get('provider'):
|
||||||
sys.tracebacklimit = 0
|
self.simpleException(
|
||||||
raise CloudflareReCaptchaProvider(
|
CloudflareReCaptchaProvider,
|
||||||
"Cloudflare reCaptcha detected, unfortunately you haven't loaded an anti reCaptcha provider "
|
"Cloudflare reCaptcha detected, unfortunately you haven't loaded an anti reCaptcha provider "
|
||||||
"correctly via the 'recaptcha' parameter."
|
"correctly via the 'recaptcha' parameter."
|
||||||
)
|
)
|
||||||
@@ -448,8 +499,10 @@ class CloudScraper(Session):
|
|||||||
if isinstance(delay, (int, float)):
|
if isinstance(delay, (int, float)):
|
||||||
self.delay = delay
|
self.delay = delay
|
||||||
except (AttributeError, ValueError):
|
except (AttributeError, ValueError):
|
||||||
sys.tracebacklimit = 0
|
self.simpleException(
|
||||||
raise CloudflareIUAMError("Cloudflare IUAM possibility malformed, issue extracing delay value.")
|
CloudflareIUAMError,
|
||||||
|
"Cloudflare IUAM possibility malformed, issue extracing delay value."
|
||||||
|
)
|
||||||
|
|
||||||
sleep(self.delay)
|
sleep(self.delay)
|
||||||
|
|
||||||
@@ -507,6 +560,7 @@ class CloudScraper(Session):
|
|||||||
|
|
||||||
if not challengeSubmitResponse.is_redirect:
|
if not challengeSubmitResponse.is_redirect:
|
||||||
return challengeSubmitResponse
|
return challengeSubmitResponse
|
||||||
|
|
||||||
else:
|
else:
|
||||||
cloudflare_kwargs = deepcopy(kwargs)
|
cloudflare_kwargs = deepcopy(kwargs)
|
||||||
cloudflare_kwargs['headers'] = updateAttr(
|
cloudflare_kwargs['headers'] = updateAttr(
|
||||||
@@ -535,6 +589,7 @@ class CloudScraper(Session):
|
|||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
return self.request(resp.request.method, resp.url, **kwargs)
|
return self.request(resp.request.method, resp.url, **kwargs)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -587,8 +642,8 @@ class CloudScraper(Session):
|
|||||||
cookie_domain = d
|
cookie_domain = d
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
sys.tracebacklimit = 0
|
cls.simpleException(
|
||||||
raise CloudflareIUAMError(
|
CloudflareIUAMError,
|
||||||
"Unable to find Cloudflare cookies. Does the site actually "
|
"Unable to find Cloudflare cookies. Does the site actually "
|
||||||
"have Cloudflare IUAM (I'm Under Attack Mode) enabled?"
|
"have Cloudflare IUAM (I'm Under Attack Mode) enabled?"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from __future__ import absolute_import
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
reCaptchaServiceUnavailable,
|
reCaptchaServiceUnavailable,
|
||||||
reCaptchaAPIError,
|
reCaptchaAPIError,
|
||||||
@@ -81,7 +80,7 @@ class captchaSolver(reCaptcha):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if response.json().get('status') is False and response.json().get('request') in errors.get(request_type):
|
if response.json().get('status') == 0 and response.json().get('request') in errors.get(request_type):
|
||||||
raise reCaptchaAPIError(
|
raise reCaptchaAPIError(
|
||||||
'{} {}'.format(
|
'{} {}'.format(
|
||||||
response.json().get('request'),
|
response.json().get('request'),
|
||||||
@@ -113,7 +112,8 @@ class captchaSolver(reCaptcha):
|
|||||||
'action': 'reportbad',
|
'action': 'reportbad',
|
||||||
'id': jobID,
|
'id': jobID,
|
||||||
'json': '1'
|
'json': '1'
|
||||||
}
|
},
|
||||||
|
timeout=30
|
||||||
),
|
),
|
||||||
check_success=_checkRequest,
|
check_success=_checkRequest,
|
||||||
step=5,
|
step=5,
|
||||||
@@ -149,7 +149,8 @@ class captchaSolver(reCaptcha):
|
|||||||
'action': 'get',
|
'action': 'get',
|
||||||
'id': jobID,
|
'id': jobID,
|
||||||
'json': '1'
|
'json': '1'
|
||||||
}
|
},
|
||||||
|
timeout=30
|
||||||
),
|
),
|
||||||
check_success=_checkRequest,
|
check_success=_checkRequest,
|
||||||
step=5,
|
step=5,
|
||||||
@@ -165,7 +166,7 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def requestSolve(self, site_url, site_key):
|
def requestSolve(self, captchaType, url, siteKey):
|
||||||
def _checkRequest(response):
|
def _checkRequest(response):
|
||||||
if response.ok and response.json().get("status") == 1 and response.json().get('request'):
|
if response.ok and response.json().get("status") == 1 and response.json().get('request'):
|
||||||
return response
|
return response
|
||||||
@@ -174,18 +175,29 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'key': self.api_key,
|
||||||
|
'pageurl': url,
|
||||||
|
'json': 1,
|
||||||
|
'soft_id': 5507698
|
||||||
|
}
|
||||||
|
|
||||||
|
data.update(
|
||||||
|
{
|
||||||
|
'method': 'userrcaptcha',
|
||||||
|
'googlekey': siteKey
|
||||||
|
} if captchaType == 'reCaptcha' else {
|
||||||
|
'method': 'hcaptcha',
|
||||||
|
'sitekey': siteKey
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
response = polling.poll(
|
response = polling.poll(
|
||||||
lambda: self.session.post(
|
lambda: self.session.post(
|
||||||
'{}/in.php'.format(self.host),
|
'{}/in.php'.format(self.host),
|
||||||
data={
|
data=data,
|
||||||
'key': self.api_key,
|
allow_redirects=False,
|
||||||
'method': 'userrecaptcha',
|
timeout=30
|
||||||
'googlekey': site_key,
|
|
||||||
'pageurl': site_url,
|
|
||||||
'json': '1',
|
|
||||||
'soft_id': '5507698'
|
|
||||||
},
|
|
||||||
allow_redirects=False
|
|
||||||
),
|
),
|
||||||
check_success=_checkRequest,
|
check_success=_checkRequest,
|
||||||
step=5,
|
step=5,
|
||||||
@@ -201,7 +213,7 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def getCaptchaAnswer(self, site_url, site_key, reCaptchaParams):
|
def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
|
||||||
jobID = None
|
jobID = None
|
||||||
|
|
||||||
if not reCaptchaParams.get('api_key'):
|
if not reCaptchaParams.get('api_key'):
|
||||||
@@ -215,7 +227,7 @@ class captchaSolver(reCaptcha):
|
|||||||
self.session.proxies = reCaptchaParams.get('proxies')
|
self.session.proxies = reCaptchaParams.get('proxies')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
jobID = self.requestSolve(site_url, site_key)
|
jobID = self.requestSolve(captchaType, url, siteKey)
|
||||||
return self.requestJob(jobID)
|
return self.requestJob(jobID)
|
||||||
except polling.TimeoutException:
|
except polling.TimeoutException:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ except ImportError:
|
|||||||
)
|
)
|
||||||
|
|
||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
|
reCaptchaException,
|
||||||
reCaptchaServiceUnavailable,
|
reCaptchaServiceUnavailable,
|
||||||
reCaptchaAPIError,
|
reCaptchaAPIError,
|
||||||
reCaptchaTimeout,
|
reCaptchaTimeout,
|
||||||
@@ -143,7 +144,7 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def requestSolve(self, site_url, site_key):
|
def requestSolve(self, url, siteKey):
|
||||||
def _checkRequest(response):
|
def _checkRequest(response):
|
||||||
if response.ok and response.text.startswith('{') and response.json().get('captchaid'):
|
if response.ok and response.text.startswith('{') and response.json().get('captchaid'):
|
||||||
return response
|
return response
|
||||||
@@ -159,9 +160,9 @@ class captchaSolver(reCaptcha):
|
|||||||
'apikey': self.api_key,
|
'apikey': self.api_key,
|
||||||
'action': 'usercaptchaupload',
|
'action': 'usercaptchaupload',
|
||||||
'interactive': 1,
|
'interactive': 1,
|
||||||
'file-upload-01': site_key,
|
'file-upload-01': siteKey,
|
||||||
'oldsource': 'recaptchav2',
|
'oldsource': 'recaptchav2',
|
||||||
'pageurl': site_url,
|
'pageurl': url,
|
||||||
'maxtimeout': self.maxtimeout,
|
'maxtimeout': self.maxtimeout,
|
||||||
'json': 1
|
'json': 1
|
||||||
},
|
},
|
||||||
@@ -179,12 +180,17 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def getCaptchaAnswer(self, site_url, site_key, reCaptchaParams):
|
def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
|
||||||
jobID = None
|
jobID = None
|
||||||
|
|
||||||
if not reCaptchaParams.get('api_key'):
|
if not reCaptchaParams.get('api_key'):
|
||||||
raise reCaptchaParameter("9kw: Missing api_key parameter.")
|
raise reCaptchaParameter("9kw: Missing api_key parameter.")
|
||||||
|
|
||||||
|
if captchaType == 'hCaptcha':
|
||||||
|
raise reCaptchaException(
|
||||||
|
'Provider does not support hCaptcha.'
|
||||||
|
)
|
||||||
|
|
||||||
self.api_key = reCaptchaParams.get('api_key')
|
self.api_key = reCaptchaParams.get('api_key')
|
||||||
|
|
||||||
if reCaptchaParams.get('maxtimeout'):
|
if reCaptchaParams.get('maxtimeout'):
|
||||||
@@ -194,7 +200,7 @@ class captchaSolver(reCaptcha):
|
|||||||
self.session.proxies = reCaptchaParams.get('proxies')
|
self.session.proxies = reCaptchaParams.get('proxies')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
jobID = self.requestSolve(site_url, site_key)
|
jobID = self.requestSolve(url, siteKey)
|
||||||
return self.requestJob(jobID)
|
return self.requestJob(jobID)
|
||||||
except polling.TimeoutException:
|
except polling.TimeoutException:
|
||||||
raise reCaptchaTimeout(
|
raise reCaptchaTimeout(
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ class reCaptcha(ABC):
|
|||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def getCaptchaAnswer(self, site_url, site_key, reCaptchaParams):
|
def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def solveCaptcha(self, site_url, site_key, reCaptchaParams):
|
def solveCaptcha(self, captchaType, url, siteKey, reCaptchaParams):
|
||||||
return self.getCaptchaAnswer(site_url, site_key, reCaptchaParams)
|
return self.getCaptchaAnswer(captchaType, url, siteKey, reCaptchaParams)
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from ..exceptions import reCaptchaParameter
|
from ..exceptions import (
|
||||||
|
reCaptchaParameter,
|
||||||
|
reCaptchaTimeout,
|
||||||
|
reCaptchaAPIError
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from python_anticaptcha import (
|
from python_anticaptcha import (
|
||||||
AnticaptchaClient,
|
AnticaptchaClient,
|
||||||
NoCaptchaTaskProxylessTask
|
NoCaptchaTaskProxylessTask,
|
||||||
|
HCaptchaTaskProxyless,
|
||||||
|
AnticaptchaException
|
||||||
)
|
)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError(
|
raise ImportError(
|
||||||
"Please install the python module 'python_anticaptcha' via pip or download it from "
|
"Please install/upgrade the python module 'python_anticaptcha' via "
|
||||||
"https://github.com/ad-m/python-anticaptcha"
|
"pip install python-anticaptcha or https://github.com/ad-m/python-anticaptcha/"
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import reCaptcha
|
from . import reCaptcha
|
||||||
@@ -23,7 +29,7 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def getCaptchaAnswer(self, site_url, site_key, reCaptchaParams):
|
def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
|
||||||
if not reCaptchaParams.get('api_key'):
|
if not reCaptchaParams.get('api_key'):
|
||||||
raise reCaptchaParameter("anticaptcha: Missing api_key parameter.")
|
raise reCaptchaParameter("anticaptcha: Missing api_key parameter.")
|
||||||
|
|
||||||
@@ -32,16 +38,30 @@ class captchaSolver(reCaptcha):
|
|||||||
if reCaptchaParams.get('proxy'):
|
if reCaptchaParams.get('proxy'):
|
||||||
client.session.proxies = reCaptchaParams.get('proxies')
|
client.session.proxies = reCaptchaParams.get('proxies')
|
||||||
|
|
||||||
task = NoCaptchaTaskProxylessTask(site_url, site_key)
|
captchaMap = {
|
||||||
|
'reCaptcha': NoCaptchaTaskProxylessTask,
|
||||||
|
'hCaptcha': HCaptchaTaskProxyless
|
||||||
|
}
|
||||||
|
|
||||||
|
task = captchaMap[captchaType](url, siteKey)
|
||||||
|
|
||||||
if not hasattr(client, 'createTaskSmee'):
|
if not hasattr(client, 'createTaskSmee'):
|
||||||
raise NotImplementedError(
|
raise NotImplementedError(
|
||||||
"Please upgrade 'python_anticaptcha' via pip or download it from "
|
"Please upgrade 'python_anticaptcha' via pip or download it from "
|
||||||
"https://github.com/ad-m/python-anticaptcha"
|
"https://github.com/ad-m/python-anticaptcha/tree/hcaptcha"
|
||||||
)
|
)
|
||||||
|
|
||||||
job = client.createTaskSmee(task)
|
job = client.createTaskSmee(task)
|
||||||
|
|
||||||
|
try:
|
||||||
|
job.join(maximum_time=180)
|
||||||
|
except (AnticaptchaException) as e:
|
||||||
|
raise reCaptchaTimeout('{}'.format(getattr(e, 'message', e)))
|
||||||
|
|
||||||
|
if 'solution' in job._last_result:
|
||||||
return job.get_solution_response()
|
return job.get_solution_response()
|
||||||
|
else:
|
||||||
|
raise reCaptchaAPIError('Job did not return `solution` key in payload.')
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ except ImportError:
|
|||||||
)
|
)
|
||||||
|
|
||||||
from ..exceptions import (
|
from ..exceptions import (
|
||||||
|
reCaptchaException,
|
||||||
reCaptchaServiceUnavailable,
|
reCaptchaServiceUnavailable,
|
||||||
reCaptchaAccountError,
|
reCaptchaAccountError,
|
||||||
reCaptchaTimeout,
|
reCaptchaTimeout,
|
||||||
@@ -154,7 +155,7 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def requestSolve(self, site_url, site_key):
|
def requestSolve(self, url, siteKey):
|
||||||
def _checkRequest(response):
|
def _checkRequest(response):
|
||||||
if response.ok and response.json().get("is_correct") and response.json().get('captcha'):
|
if response.ok and response.json().get("is_correct") and response.json().get('captcha'):
|
||||||
return response
|
return response
|
||||||
@@ -172,8 +173,8 @@ class captchaSolver(reCaptcha):
|
|||||||
'password': self.password,
|
'password': self.password,
|
||||||
'type': '4',
|
'type': '4',
|
||||||
'token_params': json.dumps({
|
'token_params': json.dumps({
|
||||||
'googlekey': site_key,
|
'googlekey': siteKey,
|
||||||
'pageurl': site_url
|
'pageurl': url
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
allow_redirects=False
|
allow_redirects=False
|
||||||
@@ -192,7 +193,7 @@ class captchaSolver(reCaptcha):
|
|||||||
|
|
||||||
# ------------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------------- #
|
||||||
|
|
||||||
def getCaptchaAnswer(self, site_url, site_key, reCaptchaParams):
|
def getCaptchaAnswer(self, captchaType, url, siteKey, reCaptchaParams):
|
||||||
jobID = None
|
jobID = None
|
||||||
|
|
||||||
for param in ['username', 'password']:
|
for param in ['username', 'password']:
|
||||||
@@ -202,11 +203,16 @@ class captchaSolver(reCaptcha):
|
|||||||
)
|
)
|
||||||
setattr(self, param, reCaptchaParams.get(param))
|
setattr(self, param, reCaptchaParams.get(param))
|
||||||
|
|
||||||
|
if captchaType == 'hCaptcha':
|
||||||
|
raise reCaptchaException(
|
||||||
|
'Provider does not support hCaptcha.'
|
||||||
|
)
|
||||||
|
|
||||||
if reCaptchaParams.get('proxy'):
|
if reCaptchaParams.get('proxy'):
|
||||||
self.session.proxies = reCaptchaParams.get('proxies')
|
self.session.proxies = reCaptchaParams.get('proxies')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
jobID = self.requestSolve(site_url, site_key)
|
jobID = self.requestSolve(url, siteKey)
|
||||||
return self.requestJob(jobID)
|
return self.requestJob(jobID)
|
||||||
except polling.TimeoutException:
|
except polling.TimeoutException:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
"ECDHE-RSA-CHACHA20-POLY1305",
|
"ECDHE-RSA-CHACHA20-POLY1305",
|
||||||
"AES128-GCM-SHA256",
|
"AES128-GCM-SHA256",
|
||||||
"AES256-GCM-SHA384",
|
"AES256-GCM-SHA384",
|
||||||
"AES128-SHA",
|
"AES128-SHA"
|
||||||
"AES256-SHA"
|
|
||||||
],
|
],
|
||||||
"releases": {
|
"releases": {
|
||||||
"Chrome/50.0.0.0": {
|
"Chrome/50.0.0.0": {
|
||||||
@@ -12825,8 +12824,7 @@
|
|||||||
"ECDHE-ECDSA-AES128-SHA",
|
"ECDHE-ECDSA-AES128-SHA",
|
||||||
"DHE-RSA-AES128-SHA",
|
"DHE-RSA-AES128-SHA",
|
||||||
"DHE-RSA-AES256-SHA",
|
"DHE-RSA-AES256-SHA",
|
||||||
"AES128-SHA",
|
"AES128-SHA"
|
||||||
"AES256-SHA"
|
|
||||||
],
|
],
|
||||||
"releases": {
|
"releases": {
|
||||||
"Firefox/50.0": {
|
"Firefox/50.0": {
|
||||||
|
|||||||
Reference in New Issue
Block a user