diff --git a/anticaptcha_examples/anticaptcah_image_to_text_example.py b/anticaptcha_examples/anticaptcah_image_to_text_example.py index 02bc304..cd8b88c 100644 --- a/anticaptcha_examples/anticaptcah_image_to_text_example.py +++ b/anticaptcha_examples/anticaptcah_image_to_text_example.py @@ -1,3 +1,5 @@ +import asyncio + from python3_anticaptcha import ImageToTextTask ANTICAPTCHA_KEY = "" @@ -17,4 +19,21 @@ save_format = 'const' . # Пример который показывает работу антикапчи при решении капчи-изображением и сохранением её в качестве ВРЕМЕННОГО файла result = ImageToTextTask.ImageToTextTask(anticaptcha_key = ANTICAPTCHA_KEY)\ .captcha_handler('http://85.255.8.26/static/image/common_image_example/800070.png') -print(result) \ No newline at end of file +print(result) + + +# Пример асинхронного запуска решения капчи +async def run(): + try: + resolve = await ImageToTextTask.aioImageToTextTask(anticaptcha_key=ANTICAPTCHA_KEY, save_format='const')\ + .captcha_handler('http://85.255.8.26/static/image/common_image_example/800070.png') + + print(resolve) + except Exception as err: + print(err) + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(run()) + loop.close() \ No newline at end of file diff --git a/anticaptcha_examples/anticaptcha_control_example.py b/anticaptcha_examples/anticaptcha_control_example.py index c715dc6..35001c2 100644 --- a/anticaptcha_examples/anticaptcha_control_example.py +++ b/anticaptcha_examples/anticaptcha_control_example.py @@ -1,5 +1,8 @@ +import asyncio + from python3_anticaptcha import AntiCaptchaControl + ANTICAPTCHA_KEY = "" # Пример метода отправляющего жалобу на неправелно решённую капчи # в качестве параметра принимает ключ антикапчи и ID неправильно решённой капчи @@ -8,4 +11,24 @@ result = AntiCaptchaControl.AntiCaptchaControl(anticaptcha_key = ANTICAPTCHA_KEY print(result) # Прмиер метода принимающего ключ аккаунта и возвращающего актуальный баланс result = AntiCaptchaControl.AntiCaptchaControl(anticaptcha_key = ANTICAPTCHA_KEY).get_balance() -print(result) \ No newline at end of file +print(result) + +# Асинхронный метод работы +async def run(): + try: + # io.IOBase + resolved = await AntiCaptchaControl.aioAntiCaptchaControl(anticaptcha_key=ANTICAPTCHA_KEY).get_balance() + + print(resolved) + resolved = await AntiCaptchaControl.aioAntiCaptchaControl(anticaptcha_key=ANTICAPTCHA_KEY)\ + .complaint_on_result(reported_id = -8) + + print(resolved) + except Exception as err: + print(err) + + +if __name__ == '__main__': + loop = asyncio.get_event_loop() + loop.run_until_complete(run()) + loop.close() \ No newline at end of file diff --git a/python3_anticaptcha/AntiCaptchaControl.py b/python3_anticaptcha/AntiCaptchaControl.py index ec267ed..a78d7d5 100644 --- a/python3_anticaptcha/AntiCaptchaControl.py +++ b/python3_anticaptcha/AntiCaptchaControl.py @@ -1,10 +1,15 @@ import requests +import aiohttp from .config import get_balance_url, incorrect_captcha_url class AntiCaptchaControl: def __init__(self, anticaptcha_key): + """ + Синхронный метод работы с балансом и жалобами + :param anticaptcha_key: Ключ антикапчи + """ self.ANTICAPTCHA_KEY = anticaptcha_key def get_balance(self): @@ -28,7 +33,35 @@ class AntiCaptchaControl: answer = requests.post(incorrect_captcha_url, json = payload) - if answer.json()['errorId'] == 0: - return True - else: - return False + return answer.json() + + +class aioAntiCaptchaControl: + def __init__(self, anticaptcha_key): + """ + Асинхронный метод работы с балансом и жалобами + :param anticaptcha_key: Ключ антикапчи + """ + self.ANTICAPTCHA_KEY = anticaptcha_key + + async def get_balance(self): + ''' + Получение баланса аккаунта + :return: Возвращает актуальный баланс + ''' + async with aiohttp.ClientSession() as session: + async with session.post(get_balance_url, json={'clientKey': self.ANTICAPTCHA_KEY}) as resp: + return await resp.json() + + async def complaint_on_result(self, reported_id): + ''' + Позволяет отправить жалобу на неправильно решённую капчу. + :param reported_id: Отправляете ID капчи на которую нужно пожаловаться + :return: Возвращает True/False, в зависимости от результата + ''' + payload = {'clientKey': self.ANTICAPTCHA_KEY, + 'taskId': reported_id, + } + async with aiohttp.ClientSession() as session: + async with session.post(incorrect_captcha_url, json=payload) as resp: + return await resp.json() \ No newline at end of file diff --git a/python3_anticaptcha/ImageToTextTask.py b/python3_anticaptcha/ImageToTextTask.py index a9d0c85..4f9377b 100644 --- a/python3_anticaptcha/ImageToTextTask.py +++ b/python3_anticaptcha/ImageToTextTask.py @@ -1,5 +1,7 @@ import requests import time +import aiohttp +import asyncio import tempfile import hashlib import os @@ -132,3 +134,144 @@ class ImageToTextTask: # Иначе возвращаем ответ сервера else: return captcha_response.json() + + + +class aioImageToTextTask: + ''' + Данный метод подходит для всинхронного решения капчи-изображение. + Подробней информацию смотрите в методе 'captcha_handler' и '__init__' + ''' + + def __init__(self, anticaptcha_key, sleep_time=5, save_format='temp', language='en', **kwargs): + ''' + Инициализация нужных переменных, создание папки для изображений и кэша + После завершения работы - удаляются временные фалйы и папки + :param anticaptcha_key: АПИ ключ капчи из кабинета пользователя + :param sleep_time: Вермя ожидания решения капчи + :param save_format: Формат в котором будет сохраняться изображение, либо как временный файл - 'temp', + либо как обычное изображение в папку созданную библиотекой - 'const'. + :param language: Язык капчи + :param **kwargs: За подробной информацией обратитесь к документации на сайте anticaptcha. + ''' + self.sleep_time = sleep_time + self.save_format = save_format + + # Пайлоад для создания задачи + self.task_payload = {"clientKey": anticaptcha_key, + "task": + { + "type": "ImageToTextTask", + }, + "languagePool": language + } + + # отправляем запрос на результат решения капчи, если ещё капча не решена - ожидаем 5 сек + # если всё ок - идём дальше + self.result_payload = {"clientKey": anticaptcha_key} + + # Если переданы ещё параметры - вносим их в payload + if kwargs: + for key in kwargs: + self.task_payload['task'].update({key: kwargs[key]}) + + async def image_temp_saver(self, captcha_link): + ''' + Метод сохраняет файл изображения как временный и отправляет его сразу на сервер для расшифровки. + :return: Возвращает ID капчи + ''' + # Скачиваем капчу + async with aiohttp.ClientSession() as session: + async with session.get(captcha_link) as resp: + content = await resp.content.readany() + + with tempfile.NamedTemporaryFile(suffix='.png') as captcha_image: + captcha_image.write(content) + # Создаём пайлоад, вводим ключ от сайта, выбираем метод ПОСТ и ждём ответа в JSON-формате + self.task_payload['task'].update({"body": base64.b64encode(captcha_image.read()).decode('utf-8')}) + # Отправляем на рукапча изображение капчи и другие парметры, + # в результате получаем JSON ответ с номером решаемой капчи + async with aiohttp.ClientSession() as session: + async with session.post(create_task_url, json=self.task_payload) as resp: + return await resp.json() + + async def image_const_saver(self, captcha_link): + ''' + Метод создаёт папку и сохраняет в неё изображение, затем передаёт его на расшифровку и удалет файл. + :return: Возвращает ID капчи + ''' + img_path = 'PythonAntiCaptchaImages' + + if not os.path.exists(img_path): + os.mkdir(img_path) + + # Скачиваем капчу + async with aiohttp.ClientSession() as session: + async with session.get(captcha_link) as resp: + content = await resp.content.readany() + + # Высчитываем хэш изображения, для того что бы сохранить его под уникальным именем + image_hash = hashlib.sha224(content).hexdigest() + + with open(os.path.join(img_path, 'im-{0}.png'.format(image_hash)), 'wb') as out_image: + out_image.write(content) + + with open(os.path.join(img_path, 'im-{0}.png'.format(image_hash)), 'rb') as captcha_image: + # Добавляем в пайлоад картинку и отправляем + self.task_payload['task'].update({"body": base64.b64encode(captcha_image.read()).decode('utf-8')}) + # Отправляем на антикапча изображение капчи и другие парметры, + # в результате получаем 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() + + # удаляем файл капчи + os.remove(os.path.join(img_path, "im-{0}.png".format(image_hash))) + return captcha_id + + # Работа с капчёй + async def captcha_handler(self, captcha_link): + ''' + Метод получает от вас ссылку на изображение, скачивает его, отправляет изображение на сервер + RuCaptcha, дожидается решения капчи и вовзращает вам результат + :param captcha_link: Ссылка на изображение + :return: Возвращает весь ответ сервера JSON-строкой. + ''' + + # согласно значения переданного параметра выбираем функцию для сохранения изображения + if self.save_format == 'const': + captcha_id = await self.image_const_saver(captcha_link) + elif self.save_format == 'temp': + captcha_id = await self.image_temp_saver(captcha_link) + else: + return """Wrong 'save_format' parameter. Valid formats: 'const' or 'temp'.\n + Неправильный 'save_format' параметр. Возможные форматы: 'const' или 'temp'.""" + + # Проверка статуса создания задачи, если создано без ошибок - извлекаем ID задачи, иначе возвращаем ответ сервера + if captcha_id['errorId'] == 0: + captcha_id = captcha_id["taskId"] + self.result_payload.update({"taskId": captcha_id}) + else: + return captcha_id + + # Ожидаем решения капчи + await asyncio.sleep(self.sleep_time) + # отправляем запрос на результат решения капчи, если не решена ожидаем + while True: + async with aiohttp.ClientSession() as session: + async with session.post(get_result_url, json=self.result_payload) as resp: + json_result = await resp.json() + + # Если ошибки нет - проверяем статус капчи + if json_result['errorId'] == 0: + # Если капча ещё не готова- ожидаем + if json_result["status"] == "processing": + await asyncio.sleep(self.sleep_time) + # если уже решена - возвращаем ответ сервера + else: + return json_result + # Иначе возвращаем ответ сервера + else: + return json_result + diff --git a/python3_anticaptcha/aioAntiCaptchaControl.py b/python3_anticaptcha/aioAntiCaptchaControl.py deleted file mode 100644 index afc6e57..0000000 --- a/python3_anticaptcha/aioAntiCaptchaControl.py +++ /dev/null @@ -1,49 +0,0 @@ -import aiohttp -import asyncio - -from .config import get_balance_url, incorrect_captcha_url - - -class AntiCaptchaControl: - def __init__(self, anticaptcha_key): - self.ANTICAPTCHA_KEY = anticaptcha_key - - def get_balance(self): - ''' - Получение баланса аккаунта - :return: Возвращает актуальный баланс - ''' - loop = asyncio.get_event_loop() - server_answer = loop.run_until_complete(self.aio_get_balance()) - loop.close() - - return server_answer - - async def aio_get_balance(self): - async with aiohttp.ClientSession() as session: - async with session.post(get_balance_url, json={'clientKey': self.ANTICAPTCHA_KEY}) as resp: - return await resp.json() - - def complaint_on_result(self, reported_id): - ''' - Позволяет отправить жалобу на неправильно решённую капчу. - :param reported_id: Отправляете ID капчи на которую нужно пожаловаться - :return: Возвращает True/False, в зависимости от результата - ''' - loop = asyncio.get_event_loop() - server_answer = loop.run_until_complete(self.aio_complaint_on_result(reported_id)) - loop.close() - - if server_answer['errorId'] == 0: - return True - else: - return False - - - async def aio_complaint_on_result(self, reported_id): - payload = {'clientKey': self.ANTICAPTCHA_KEY, - 'taskId': reported_id, - } - async with aiohttp.ClientSession() as session: - async with session.post(incorrect_captcha_url, json=payload) as resp: - return await resp.json() diff --git a/python3_anticaptcha/aioImageToTextTask.py b/python3_anticaptcha/aioImageToTextTask.py deleted file mode 100644 index 3c32f06..0000000 --- a/python3_anticaptcha/aioImageToTextTask.py +++ /dev/null @@ -1,156 +0,0 @@ -import aiohttp -import asyncio -import tempfile -import hashlib -import os -import base64 - -from .config import create_task_url, get_result_url, app_key - - -class ImageToTextTask: - ''' - Данный метод подходит для решения капчи-изображение. - Подробней информацию смотрите в методе 'captcha_handler' и '__init__' - ''' - - def __init__(self, anticaptcha_key, sleep_time=5, save_format='temp', language='en', **kwargs): - ''' - Инициализация нужных переменных, создание папки для изображений и кэша - После завершения работы - удаляются временные фалйы и папки - :param anticaptcha_key: АПИ ключ капчи из кабинета пользователя - :param sleep_time: Вермя ожидания решения капчи - :param save_format: Формат в котором будет сохраняться изображение, либо как временный файл - 'temp', - либо как обычное изображение в папку созданную библиотекой - 'const'. - :param language: Язык капчи - :param **kwargs: За подробной информацией обратитесь к документации на сайте anticaptcha. - ''' - self.sleep_time = sleep_time - self.save_format = save_format - - # Пайлоад для создания задачи - self.task_payload = {"clientKey": anticaptcha_key, - "task": - { - "type": "ImageToTextTask", - }, - "languagePool": language - } - - # отправляем запрос на результат решения капчи, если ещё капча не решена - ожидаем 5 сек - # если всё ок - идём дальше - self.result_payload = {"clientKey": anticaptcha_key} - - # Если переданы ещё параметры - вносим их в payload - if kwargs: - for key in kwargs: - self.task_payload['task'].update({key: kwargs[key]}) - - # Создаём асинхронный цикл - self.loop = asyncio.get_event_loop() - - async def image_temp_saver(self, captcha_link): - ''' - Метод сохраняет файл изображения как временный и отправляет его сразу на сервер для расшифровки. - :return: Возвращает ID капчи - ''' - # Скачиваем капчу - async with aiohttp.ClientSession() as session: - async with session.get(captcha_link) as resp: - content = await resp.content.readany() - - with tempfile.NamedTemporaryFile(suffix='.png') as captcha_image: - captcha_image.write(content) - # Создаём пайлоад, вводим ключ от сайта, выбираем метод ПОСТ и ждём ответа в JSON-формате - self.task_payload['task'].update({"body": base64.b64encode(captcha_image.read()).decode('utf-8')}) - # Отправляем на рукапча изображение капчи и другие парметры, - # в результате получаем JSON ответ с номером решаемой капчи - async with aiohttp.ClientSession() as session: - async with session.post(create_task_url, json=self.task_payload) as resp: - return await resp.json() - - async def image_const_saver(self, captcha_link): - ''' - Метод создаёт папку и сохраняет в неё изображение, затем передаёт его на расшифровку и удалет файл. - :return: Возвращает ID капчи - ''' - img_path = 'PythonAntiCaptchaImages' - - if not os.path.exists(img_path): - os.mkdir(img_path) - - # Скачиваем капчу - async with aiohttp.ClientSession() as session: - async with session.get(captcha_link) as resp: - content = await resp.content.readany() - - # Высчитываем хэш изображения, для того что бы сохранить его под уникальным именем - image_hash = hashlib.sha224(content).hexdigest() - - with open(os.path.join(img_path, 'im-{0}.png'.format(image_hash)), 'wb') as out_image: - out_image.write(content) - - with open(os.path.join(img_path, 'im-{0}.png'.format(image_hash)), 'rb') as captcha_image: - # Добавляем в пайлоад картинку и отправляем - self.task_payload['task'].update({"body": base64.b64encode(captcha_image.read()).decode('utf-8')}) - # Отправляем на антикапча изображение капчи и другие парметры, - # в результате получаем 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() - - # удаляем файл капчи - os.remove(os.path.join(img_path, "im-{0}.png".format(image_hash))) - return captcha_id - - # Работа с капчёй - def captcha_handler(self, captcha_link): - ''' - Метод получает от вас ссылку на изображение, скачивает его, отправляет изображение на сервер - RuCaptcha, дожидается решения капчи и вовзращает вам результат - :param captcha_link: Ссылка на изображение - :return: Возвращает весь ответ сервера JSON-строкой. - ''' - - # согласно значения переданного параметра выбираем функцию для сохранения изображения - if self.save_format == 'const': - captcha_id = self.loop.run_until_complete(self.image_const_saver(captcha_link)) - elif self.save_format == 'temp': - captcha_id = self.loop.run_until_complete(self.image_temp_saver(captcha_link)) - else: - return """Wrong 'save_format' parameter. Valid formats: 'const' or 'temp'.\n - Неправильный 'save_format' параметр. Возможные форматы: 'const' или 'temp'.""" - - # Проверка статуса создания задачи, если создано без ошибок - извлекаем ID задачи, иначе возвращаем ответ сервера - if captcha_id['errorId'] == 0: - captcha_id = captcha_id["taskId"] - self.result_payload.update({"taskId": captcha_id}) - else: - return captcha_id - - anticaptcha_answer = self.loop.run_until_complete(self.aio_captcha_handler()) - self.loop.close() - - return anticaptcha_answer - - async def aio_captcha_handler(self): - # Ожидаем решения капчи - #await asyncio.sleep(self.sleep_time) - # отправляем запрос на результат решения капчи, если не решена ожидаем - while True: - async with aiohttp.ClientSession() as session: - async with session.post(get_result_url, json=self.result_payload) as resp: - json_result = await resp.json() - - # Если ошибки нет - проверяем статус капчи - if json_result['errorId'] == 0: - # Если капча ещё не готова- ожидаем - if json_result["status"] == "processing": - await asyncio.sleep(self.sleep_time) - # если уже решена - возвращаем ответ сервера - else: - return json_result - # Иначе возвращаем ответ сервера - else: - return json_result \ No newline at end of file