Пишем чат бота для ВКонтакте на python с помощью longpoll. Часть вторая. Двойные циклы, исключения и прочая ересь

  • Tutorial
Приветствую, Хабр. Эта статья является продолжением вот этой. Перед прочтением настоятельно рекомендую ознакомится с ней если вы этого не сделали ранее.

Сегодня вы узнаете:

  1. Как получать более одного ответа, пусть и колхозно
  2. Как подключить к этому яндекс переводчик
  3. И как писать пользователю что он сделал всё неправильно

Api яндекс переводчика


У яндекс переводчика есть неплохой api его мы и будем использовать. Внимательно изучаем документацию и в бой. Но тут Яндекс подкладывает нам свинью.
Требования к использованию результатов перевода
Согласно Лицензии на использование Яндекс.Переводчика над или под результатом перевода должен быть указан текст Переведено сервисом «Яндекс.Переводчик» с активной ссылкой на страницу translate.yandex.ru.

Требования к расположению текста
Текст должен быть указан:
в описании программного продукта;
в справке о программном продукте;
на официальном сайте программного продукта;
на всех страницах или экранах, где используются данные сервиса.
Ну мы люди не гордые, переживём.

Как оно работает


Пользователь пишет нам сообщение, мы спрашиваем на какой язык он хочет перевести фразу. После спрашиваем текст, который надо перевести и отправляем результат.

Техническая реализация


Получаем api ключ
Используем вот эту библиотеку

from yandex_translate import YandexTranslate #Импортируем библиотеку
translate = YandexTranslate('Вставьте ключ сюда')

Пинаем longpoll как я описывал в 1-й части.

if event.text == 'Перевод': #если пришло сообщение с текстом "Перевод"
     if event.from_user:
         vk.messages.send( #Отправляем сообщение
             user_id=event.user_id,
             message='На какой язык? Указывать двумя буквами.\n Например: Русский - ru, Английский - en' #C текстом "На какой язык? Указывать двумя буквами.\n Например: Русский - ru, Английский - en". Замечание текст должен быть одной строкой
	 )
     elif event.from_chat:
        vk.messages.send( #Тоже самое, но для бесед
            chat_id=event.chat_id,
            message='На какой язык? Указывать двумя буквами.\n Например: Русский - ru, Английский - en'
	)
     flag = 0 #Шаманский танец для выхода из 2-х циклов
     for event in longpoll.listen():
         if event.type == VkEventType.MESSAGE_NEW and event.to_me and event.text: #Если получили сообщение с текстом
         trTo = event.text #Сохраняем текст в переменную
             if event.from_user:
                 vk.messages.send( #Отправляем сообщение
                     user_id=event.user_id,
                     message='Введите фразу, которую надо перевести '
		 )
             elif event.from_chat:
                 vk.messages.send( #Тоже самое, но для бесед
                      chat_id=event.chat_id,
                      message='Введите фразу, которую надо перевести '
	         )
             for event in longpoll.listen():
                 if event.type == VkEventType.MESSAGE_NEW and event.to_me and event.text: #Если получили сообщение с текстом
                     trNormal = 1 #Колхозный флаг для ошибки
                     try: #Исключение, о них поговорим ниже
                         trFrom = translate.detect(event.text) #Определяем язык
                         trResult = translate.translate(event.text, trFrom + '-' + trTo) #Переводим
                     except Exception as e: #Если что-то пошло не так
                         trNormal = 0 #Пинаем флаг ошибки
                         print("Exception:", e) #Пишем в консоль
                         pass
                     if trNormal == 1: #Если всё хорошо
                         if event.from_user:
                             vk.messages.send( #Отправляем сообщение
                             user_id=event.user_id,
                             message='Переведено сервисом «Яндекс.Переводчик» translate.yandex.ru\n' + str(trResult['text'])
                             )
                             flag = 1 #Выходим из 2-х циклов
                             break
                         elif event.from_chat:
                             vk.messages.send( #Тоже самое, но для бесед
                                 chat_id=event.chat_id,
                                 message='Переведено сервисом «Яндекс.Переводчик» translate.yandex.ru\n' + str(trResult['text'])
		             )
                             flag = 1 
                             break
                         if trNormal == 0: #Если всё плохо
                             if event.from_user:
                                 vk.messages.send( #Отправляем сообщение
                                 user_id=event.user_id,
                                 message='Неправильно введён язык' #Т.к. всё плохо в 99% случаев из-за того, что пользователь написал язык неправильно пишем ему об этом
                                 )
                                 flag = 1 #Выходим из 2-х циклов
                                 break
                             elif event.from_chat:
                                 vk.messages.send( #Тоже самое, но для бесед
                                     chat_id=event.chat_id,
                                     message='Неправильно введён язык'
				 )
                                 flag = 1
                                 break
             if flag == 1: #Шаманский танец для выхода из 2-х циклов
                 break

Что такое исключения и с чем их едят


Исключения — это такая штука, которая в случае ошибки бежит и говорит нам об этом. Для обработки исключений используется конструкция try — except.

Давайте попробуем реализовать наш код без этой конструкции.

-Перевод
-На какой язык? Указывать двумя буквами.
Например: Русский — ru, Английский — en
-en
-Введите фразу, которую надо перевести
-Привет хабр
-Переведено сервисом «Яндекс.Переводчик» translate.yandex.ru
['Hi Habr']

Ну вот работает, и зачем нам ваши исключения?

А вот зачем:
-Перевод
-На какой язык? Указывать двумя буквами.
Например: Русский — ru, Английский — en
-абракадабра
-Введите фразу, которую надо перевести
-Привет хабр
...

Тем временем в консоли:

Traceback (most recent call last):
  File "C:\Py_trash\habrex.py", line 112, in <module>
    main()
  File "C:\Py_trash\habrex.py", line 78, in main
    trResult = translate.translate(event.text, trFrom + '-' + trTo)
  File "C:\Users\Hukuma\AppData\Local\Programs\Python\Python37-32\lib\site-packages\yandex_translate\__init__.py", line 150, in translate
    raise YandexTranslateException(status_code)
yandex_translate.YandexTranslateException: None

А с исключениями:

-Перевод
-На какой язык? Указывать двумя буквами.
Например: Русский — ru, Английский — en
-Абракадабра
-Введите фразу, которую надо перевести
-Привет хабр
-Неправильно введён язык

Более подробно разберу конструкцию try — except:

try:
    #sample code
except Exception:
    #код который выполнится ТОЛЬКО если будет исключение

Приведу пример с wikipedia api:

 try:
    result = str(wikipedia.summary(event.text))
except wikipedia.exceptions.PageError:
    print('Ничего не найдено')
except wikipedia.exceptions.DisambiguationError:
    print('Неоднозначность')

Как вы поняли, исключений может быть несколько.

На этом я с вами прощаюсь. Всего хорошего
Поделиться публикацией

Похожие публикации

Комментарии 2
    +2

    Думаю, в данном случае, вместо мешанины из нескольких циклов можно было бы простенький конечный автомат использовать. Реализовать его как какой-нибудь класс Dialog. Тогда мы бы обошлись одним циклом. Просто бы принимали event, передавали бы его инстансу класса ( для каждого пользователя свой ), и инстанс бы сам решал, что именно нужно сделать с event.

      0
      flag = 0 #Шаманский танец для выхода из 2-х циклов

      Оберните двойной цикл в функцию и делайте return в месте выхода из обоих циклов.

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое