From 485a1d385874144b4f2f3d9506d1717608e76731 Mon Sep 17 00:00:00 2001 From: Andrei Date: Tue, 15 May 2018 14:12:20 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B8=D0=B7=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=B2=20=D0=BA=D0=BE=D0=B4=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B5=20base64=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B5=D0=B7=D0=B4=20=D0=BD=D0=B0=20=D1=81=D0=B8=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D0=BA=D1=81=D0=B8=D1=81=D0=B8=20=D1=84=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D0=B0=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=BA=20f''=20-=20Python=203.6=20?= =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=BC=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE?= =?UTF-8?q?=20=D0=B2=D0=B2=D0=B5=D0=B4=D1=91=D0=BD=D0=BD=D0=BE=D0=B5=20?= =?UTF-8?q?=D0=B2=D1=80=D0=B5=D0=BC=D1=8F=20=D0=B4=D0=BB=D1=8F=20=D0=BE?= =?UTF-8?q?=D0=B6=D0=B8=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B5=D1=88?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=B0=D0=BF=D1=87=D0=B8=20?= =?UTF-8?q?=D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BC?= =?UTF-8?q?=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=20=D1=82?= =?UTF-8?q?=D1=80=D0=B5=D0=B1=D1=83=D0=B5=D0=BC=D0=BE=D0=B9=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=81=D0=B8=D0=B8=20aiohttp=20=D0=BD=D0=B0=203+?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 + python3_anticaptcha/FunCaptchaTask.py | 48 ++++++------ python3_anticaptcha/ImageToTextTask.py | 76 ++++++++++++++----- python3_anticaptcha/NoCaptchaTask.py | 3 + python3_anticaptcha/NoCaptchaTaskProxyless.py | 10 ++- python3_anticaptcha/errors.py | 5 +- setup.py | 6 +- 7 files changed, 101 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 3874e8a..90687ae 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # python3-anticaptcha +[![PyPI version](https://badge.fury.io/py/python3-anticaptcha.svg)](https://badge.fury.io/py/python3-anticaptcha) +[![Code Climate](https://codeclimate.com/github/AndreiDrang/python3-anticaptcha/badges/gpa.svg)](https://codeclimate.com/github/AndreiDrang/python3-anticaptcha) + Python 3 library for AntiCaptcha. [Application in AppCenter](https://anti-captcha.com/clients/tools/appcenter/app/867). diff --git a/python3_anticaptcha/FunCaptchaTask.py b/python3_anticaptcha/FunCaptchaTask.py index 82873f0..03937ae 100644 --- a/python3_anticaptcha/FunCaptchaTask.py +++ b/python3_anticaptcha/FunCaptchaTask.py @@ -18,20 +18,22 @@ class FunCaptchaTask: :param kwargs: Можно передать необязательные параметры и переопределить userAgent, все необязательные параметры описаны в документации к API на сайте антикапчи """ + if sleep_time < 5: + raise ValueError(f'Параметр `sleep_time` должен быть не менее 5. Вы передали - {sleep_time}') self.sleep_time = sleep_time # Пайлоад для создания задачи self.task_payload = {"clientKey": anticaptcha_key, - "task": - { - "type": "FunCaptchaTask", - "userAgent": user_agent_data, - "proxyType": proxyType, - "proxyAddress": proxyAddress, - "proxyPort": proxyPort, - }, - "softId": app_key - } + "task": + { + "type": "FunCaptchaTask", + "userAgent": user_agent_data, + "proxyType": proxyType, + "proxyAddress": proxyAddress, + "proxyPort": proxyPort, + }, + "softId": app_key + } # пайлоад для получения ответа сервиса self.result_payload = {"clientKey": anticaptcha_key} @@ -50,7 +52,7 @@ class FunCaptchaTask: :return: Возвращает ответ сервера в виде JSON(ответ так же можно глянуть в документации антикапчи) """ self.task_payload['task'].update({"websiteURL": websiteURL, - "websiteKey": websitePublicKey}) + "websiteKey": websitePublicKey}) # Отправляем на антикапча параметры фанкапич, # в результате получаем JSON ответ содержащий номер решаемой капчи captcha_id = requests.post(create_task_url, json=self.task_payload, **kwargs).json() @@ -95,20 +97,22 @@ class aioFunCaptchaTask: :param kwargs: Можно передать необязательные параметры и переопределить userAgent, все необязательные параметры описаны в документации к API на сайте антикапчи """ + if sleep_time < 5: + raise ValueError(f'Параметр `sleep_time` должен быть не менее 5. Вы передали - {sleep_time}') self.sleep_time = sleep_time # Пайлоад для создания задачи self.task_payload = {"clientKey": anticaptcha_key, - "task": - { - "type": "FunCaptchaTask", - "userAgent": user_agent_data, - "proxyType": proxyType, - "proxyAddress": proxyAddress, - "proxyPort": proxyPort, - }, - "softId": app_key - } + "task": + { + "type": "FunCaptchaTask", + "userAgent": user_agent_data, + "proxyType": proxyType, + "proxyAddress": proxyAddress, + "proxyPort": proxyPort, + }, + "softId": app_key + } # пайлоад для получения ответа сервиса self.result_payload = {"clientKey": anticaptcha_key} @@ -127,7 +131,7 @@ class aioFunCaptchaTask: :return: Возвращает ответ сервера в виде JSON(ответ так же можно глянуть в документации антикапчи) """ self.task_payload['task'].update({"websiteURL": websiteURL, - "websiteKey": websitePublicKey}) + "websiteKey": websitePublicKey}) # Отправляем на антикапча параметры фанкапич, # в результате получаем JSON ответ содержащий номер решаемой капчи async with aiohttp.ClientSession() as session: diff --git a/python3_anticaptcha/ImageToTextTask.py b/python3_anticaptcha/ImageToTextTask.py index b2724e3..59d612a 100644 --- a/python3_anticaptcha/ImageToTextTask.py +++ b/python3_anticaptcha/ImageToTextTask.py @@ -28,9 +28,17 @@ class ImageToTextTask: :param language: Язык капчи :param **kwargs: За подробной информацией обратитесь к документации на сайте anticaptcha. ''' + if sleep_time < 5: + raise ValueError(f'Параметр `sleep_time` должен быть не менее 5. Вы передали - {sleep_time}') self.sleep_time = sleep_time - self.save_format = save_format - + # проверяем переданный параметр способа сохранения капчи + if save_format in ['const', 'temp']: + self.save_format = save_format + else: + raise ValueError('\nПередан неверный формат сохранения файла изображения. ' + f'\n\tВозможные варинты: `temp` и `const`. Вы передали - `{save_format}`' + '\nWrong `save_format` parameter. Valid params: `const` or `temp`.' + f'\n\tYour param - `{save_format}`') # Пайлоад для создания задачи self.task_payload = {"clientKey": anticaptcha_key, "task": @@ -94,8 +102,9 @@ class ImageToTextTask: def read_captcha_image_file(self, content, content_type="file"): """ - Функция отвечает за чтение уже сохранённого файла + Функция отвечает за чтение уже сохранённого файла или файла в уодировке base64 :param content: Параметр строка-путь указывающий на изображение капчи для отправки её на сервер + :param content_type: Тип переданной переменной. Возможны варианты: `file` и `base64` :return: Возвращает ID капчи """ try: @@ -106,12 +115,15 @@ class ImageToTextTask: elif content_type == "base64": self.task_payload["task"].update({"body": content}) else: - raise Exception + raise ValueError('\nПередан неверный формат файла.' + f'\n\tВозможные варинты: `file` и `base64`. Вы передали - `{content_type}`' + f'\nWrong `content_type` parameter. Valid params: `file` or `base64`.' + f'\n\tYour param - `{content_type}`') # Отправляем на антикапча изображение капчи и другие парметры, # в результате получаем JSON ответ содержащий номер решаемой капчи captcha_id = requests.post(create_task_url, json=self.task_payload).json() - except IOError: - raise ReadError() + except (IOError, FileNotFoundError) as err: + raise ReadError(err) return captcha_id @@ -122,6 +134,7 @@ class ImageToTextTask: RuCaptcha, дожидается решения капчи и вовзращает вам результат :param captcha_link: Ссылка на изображение :param captcha_file: Необязательный параметр, служит для открытия уже скачанных файлов изображений. + :param captcha_base64: Загрузка изображения в кодировке base64 :return: Возвращает весь ответ сервера JSON-строкой. ''' if captcha_file: @@ -183,8 +196,17 @@ class aioImageToTextTask: :param language: Язык капчи :param **kwargs: За подробной информацией обратитесь к документации на сайте anticaptcha. ''' + if sleep_time < 5: + raise ValueError(f'Параметр `sleep_time` должен быть не менее 10. Вы передали - {sleep_time}') self.sleep_time = sleep_time - self.save_format = save_format + # проверяем переданный параметр способа сохранения капчи + if save_format in ['const', 'temp']: + self.save_format = save_format + else: + raise ValueError('\nПередан неверный формат сохранения файла изображения. ' + f'\n\tВозможные варинты: `temp` и `const`. Вы передали - `{save_format}`' + '\nWrong `save_format` parameter. Valid params: `const` or `temp`.' + f'\n\tYour param - `{save_format}`') # Пайлоад для создания задачи self.task_payload = {"clientKey": anticaptcha_key, @@ -260,21 +282,35 @@ class aioImageToTextTask: os.remove(os.path.join(img_path, "im-{0}.png".format(image_hash))) return captcha_id - async def read_captcha_image_file(self, content): + async def read_captcha_image_file(self, content, content_type='file'): + """ + Функция отвечает за чтение уже сохранённого файла или файла в уодировке base64 + :param content: Параметр строка-путь указывающий на изображение капчи для отправки её на сервер + :param content_type: Тип переданной переменной. Возможны варианты: `file` и `base64` + :return: Возвращает ID капчи + """ try: - with open(content, 'rb') as captcha_image: - # Добавляем в пайлоад картинку и отправляем - self.task_payload['task'].update({"body": base64.b64encode(captcha_image.read()).decode('utf-8')}) - # Отправляем на антикапча изображение капчи и другие парметры, - # в результате получаем JSON ответ содержащий номер решаемой капчи - captcha_id = requests.post(create_task_url, json=self.task_payload).json() - except IOError: - raise ReadError() - + if content_type == "file": + with open(content, 'rb') as captcha_image: + # Добавляем в пайлоад картинку и отправляем + self.task_payload['task'].update({"body": base64.b64encode(captcha_image.read()).decode('utf-8')}) + elif content_type == "base64": + self.task_payload["task"].update({"body": content}) + else: + raise ValueError('\nПередан неверный формат файла.' + f'\n\tВозможные варинты: `file` и `base64`. Вы передали - `{content_type}`' + f'\nWrong `content_type` parameter. Valid params: `file` or `base64`.' + f'\n\tYour param - `{content_type}`') + # Отправляем на антикапча изображение капчи и другие парметры, + # в результате получаем JSON ответ содержащий номер решаемой капчи + captcha_id = requests.post(create_task_url, json = self.task_payload).json() + except (IOError, FileNotFoundError) as err: + raise ReadError(err) + return captcha_id # Работа с капчёй - async def captcha_handler(self, captcha_link = None, captcha_file = None): + async def captcha_handler(self, captcha_link = None, captcha_file = None, captcha_base64=None): ''' Метод получает от вас ссылку на изображение, скачивает его, отправляет изображение на сервер RuCaptcha, дожидается решения капчи и вовзращает вам результат @@ -283,7 +319,9 @@ class aioImageToTextTask: ''' # если был передан линк на локальный скачаный файл if captcha_file: - captcha_id = await self.read_captcha_image_file(captcha_file) + captcha_id = self.read_captcha_image_file(captcha_file, content_type="file") + elif captcha_base64: + captcha_id = self.read_captcha_image_file(captcha_base64, content_type="base64") elif captcha_link: # согласно значения переданного параметра выбираем функцию для сохранения изображения if self.save_format == 'const': diff --git a/python3_anticaptcha/NoCaptchaTask.py b/python3_anticaptcha/NoCaptchaTask.py index f1d555b..8028fb2 100644 --- a/python3_anticaptcha/NoCaptchaTask.py +++ b/python3_anticaptcha/NoCaptchaTask.py @@ -19,6 +19,9 @@ class NoCaptchaTask: :param sleeptime: Время ожидания решения :param kwargs: Необязательные параметры, можно переопределить userAgent """ + + if sleep_time < 5: + raise ValueError(f'Параметр `sleep_time` должен быть не менее 5. Вы передали - {sleep_time}') self.sleep_time = sleep_time # Пайлоад для создания задачи diff --git a/python3_anticaptcha/NoCaptchaTaskProxyless.py b/python3_anticaptcha/NoCaptchaTaskProxyless.py index 3acc56f..f3ba1a9 100644 --- a/python3_anticaptcha/NoCaptchaTaskProxyless.py +++ b/python3_anticaptcha/NoCaptchaTaskProxyless.py @@ -14,7 +14,8 @@ class NoCaptchaTaskProxyless: :param sleep_time: Время ожидания решения капчи :param kwargs: Другие необязательные параметры из документации """ - self.ANTICAPTCHA_KEY = anticaptcha_key + if sleep_time < 5: + raise ValueError(f'Параметр `sleep_time` должен быть не менее 5. Вы передали - {sleep_time}') self.sleep_time = sleep_time # Пайлоад для создания задачи @@ -27,7 +28,7 @@ class NoCaptchaTaskProxyless: } # Пайлоад для получения результата - self.result_payload = {"clientKey": self.ANTICAPTCHA_KEY} + self.result_payload = {"clientKey": anticaptcha_key} # Если переданы ещё параметры - вносим их в payload if kwargs: @@ -84,7 +85,8 @@ class aioNoCaptchaTaskProxyless: :param sleep_time: Время ожидания решения капчи :param kwargs: Другие необязательные параметры из документации """ - self.ANTICAPTCHA_KEY = anticaptcha_key + if sleep_time < 5: + raise ValueError(f'Параметр `sleep_time` должен быть не менее 5. Вы передали - {sleep_time}') self.sleep_time = sleep_time # Пайлоад для создания задачи @@ -97,7 +99,7 @@ class aioNoCaptchaTaskProxyless: } # Пайлоад для получения результата - self.result_payload = {"clientKey": self.ANTICAPTCHA_KEY} + self.result_payload = {"clientKey": anticaptcha_key} # Если переданы ещё параметры - вносим их в payload if kwargs: diff --git a/python3_anticaptcha/errors.py b/python3_anticaptcha/errors.py index 372a0f9..b40aa3d 100644 --- a/python3_anticaptcha/errors.py +++ b/python3_anticaptcha/errors.py @@ -8,8 +8,9 @@ class DownloadError(AntiCaptchaApiException): class ReadError(AntiCaptchaApiException): - def __init__(self): - AntiCaptchaApiException.__init__(self, """\nПораждается, при проблеме во время чтения сохранённого файла.""") + def __init__(self, error): + AntiCaptchaApiException.__init__(self, """\nПораждается, при проблеме во время чтения сохранённого файла. + \n\t{0}""".format(error)) class ParamError(AntiCaptchaApiException): diff --git a/setup.py b/setup.py index 09883dc..87abe50 100644 --- a/setup.py +++ b/setup.py @@ -2,14 +2,14 @@ from setuptools import setup setup( name='python3-anticaptcha', - version='0.9.2', + version='0.9.3', author='AndreiDrang, redV0ID', packages=['python3_anticaptcha'], install_requires=[ 'fake-useragent==0.1.10', 'requests>=2.18', - 'aiohttp>=2.3' + 'aiohttp>=3' ], description='Python 3 AntiCaptcha library.', url='https://github.com/AndreiDrang/python3-anticaptcha', @@ -25,5 +25,5 @@ setup( python-library python-anticaptcha anticaptcha-client''', - python_requires='>=3.5.0', + python_requires='>=3.6', )