Cat

AIOgram3 13. Прогноз погоды в боте - OpenWeatherMap

В этом посте я расскажу о том, как получить API-ключ для OpenWeatherMap и как реализовать получение погоды в Telegram-боте.

Все статьи

Icon Link

Дополнительные материалы

Icon Link

Реклама

Icon Link
Telegram-бот на AIOgram3 proDream 03 Октябрь 2023 Просмотров: 1230

Самое востребованное в чате и наверное, одно из самых простых применений бот - прогноз погоды.

Использовать будем сервис OpenWeatherMap.

На бесплатном тарифе нам доступно 60 запросов в минуту и 1000 в день.

 

Регистрация и получение API-ключа.

Начнём с регистрации и получение ключа для API. После его получения, он начинает действовать в течении "пары часов", как раз успеем написать код.

Переходим на сайт: https://home.openweathermap.org/users/sign_in
Нажимаем на "Create an Account."

Вводим ник, почту, два раза пароль и отмечаем две первые галочки. Другие три галочки не трогаем, если конечно вы не желаете получать спам. Проходим капчу и нажимаем "Create Account".

Далее нас спросят с какой мы целью тут. Я выбрал "Education/Science". И ведь не соврал 😉. Нажимаем "Save".

 

Далее необходимо подтвердить электронную почту.

Сверху справа нажимаем на свой ник, в выпадающем списке выбираем пункт "My API keys". Оказываемся на странице, где уже есть один ключ. Также после подтверждения почты, ключ и сопутствующая информация придёт на почту.

 

Как я и упомянул ранее, он активируется не сразу, а спустя какое-то время, поэтому переходим к коду.

 

Добавляем ключ.

Для начала, добавим API-ключ в наши "секреты".

Откроем файл settings.py и добавим новую строку в классе Secrets:

weather_key: str = 'ваш ключ'

 

Получение погоды.

В пакете utils создадим новый файл get_weather.py.

Создаём функцию request_weather, принимающую один аргумент city.

 

Код функции:

import requests  

from botlogic.settings import Secrets


def request_weather(city):  
    result = requests.get("https://api.openweathermap.org/data/2.5/find",  
                          params={  
                              'q': city,  
                              'type': 'like',  
                              'units': 'metric',  
                              'lang': 'ru',  
                              'APPID': Secrets.weather_key,  
                          }).json()  
    if result['count']  0:  
        return 0  
    else:  
        return generate_result(result, city)

 

В переменную result попадает JSON с ответом от сервера. 
С помощью библиотеки requests делаем GET-запрос. Первым аргументом передаём API URL.
Вторым аргументом передаём словарь параметров, подробнее по пунктам:

  • q - отправляемый запрос, в нашем случае это город.
  • type - тип поиска, в нашем случае ищем по совпадению.
  • units - система измерения, в нашем случае метрическая.
  • lang - язык.
  • APPID - API-ключ.

Далее идёт проверка, если в ответе count равен нулю, то либо пользователь ошибся в названии города, либо такого города нет в базе сервиса. Возвращаем 0.
Иначе, возвращаем результат выполнения функции генерирующей строку с результатом.

 

Парсинг ответа и генерация строки с результатом.

Под функцией request_weather создаём новую функцию generate_result, принимающую данные из сервиса data и город city.

 

Код функции:

def generate_result(data, city):
    temp = int(data['list'][0]['main']['temp'])
    feels_like = data['list'][0]['main']['feels_like']
    pressure = int(data['list'][0]['main']['pressure']) * 0.75
    humidity = data['list'][0]['main']['humidity']
    wind_speed = int(data['list'][0]['wind']['speed'])
    rain = 'не ожидается' if data['list'][0]['rain'] is None else 'ожидается'
    snow = 'не ожидается' if data['list'][0]['snow'] is None else 'ожидается'
    weather = data['list'][0]['weather'][0]['description']
    return f'''
<b>Прогноз погоды в городе {city}</b>

Сейчас температура {temp}°C
Ощущается как {feels_like}°
⛅️{weather}⛅️  
💨 Скорость ветра {wind_speed}м/с 💨
Давление {pressure} мм рт.ст.
Влажность {humidity}%
💦 Дождь {rain}
❄️ Снег {snow}
'''

 

Тут мы из ответа получаем значения в 8 переменных, затем формируем строку с результатом.

Строку и необходимые данные можно кастомизировать по желанию.

 

Команда получения погоды.

Теперь перейдём к созданию команды. В пакете handlers создадим файл weather_fsm.py.

Создадим асинхронную функцию get_weather_command, принимающую два аргумента: message и state.

В теле функции прописываем две команды:

  • Отправка сообщения пользователю. В сообщении просим ввести город или отменить запрос.
  • Переход на следующий шаг в машине состояний.

 

Код функции:

from aiogram.fsm.context import FSMContext  
from aiogram.types import Message  

from botlogic import views  
from botlogic.utils.statesform import GetWeatherSteps  


async def get_weather_command(message: Message, state: FSMContext):  
    await message.answer(views.enter_city())  
    await state.set_state(GetWeatherSteps.BY_CITY)

 

Для первой команды необходимо открыть файл views.py и создать функцию enter_city, возвращающую строку с просьбой ввести город или отменить запрос.

 

Для второй команды необходимо открыть файл statesform.py и создать новый класс GetWeatherSteps:

class GetWeatherSteps(StatesGroup):  
    BY_CITY = State()

 

Возвращаемся в файл weather_fsm.py и ниже создаём вторую функцию get_by_city.

 

Код функции:

from botlogic.utils.get_weather import request_weather
from botlogic.settings import bot

async def get_by_city(message: Message, state: FSMContext):
    if message.text.lower()  'отмена':
        await message.answer(views.abort_weather())
        await state.clear()
    else:
        result = request_weather(message.text)
        if result:
            await message.reply(result)
            await message.answer(views.weather_request_done())
            await state.clear()
        else:
            await bot.send_message(message.chat.id, views.weather_wrong_city())
            await state.set_state(GetWeatherSteps.BY_CITY)

 

Первым делом проверяем, отменил пользователь запрос или нет.
Если запрос отменён, выводим сообщение и очищаем состояние.

 

Если отмены не произошло, вызываем функцию получения погоды, передав туда сообщение пользователя.

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

 

Иначе, если вернулся 0, просим пользователя повторить попытку или отменить запрос.

 

Готово. Осталось только зарегистрировать команды и прописать в меню.

 

Регистрация команды.

Откроем файл main.py и найдем другие зарегистрированные команды.

Ниже добавим следующие строки:

from botlogic.handlers import weather_fsm
from botlogic.utils.statesform import GetWeatherSteps


dp.message.register(weather_fsm.get_weather_command, Command(commands='weather'))  
dp.message.register(weather_fsm.get_by_city, GetWeatherSteps.BY_CITY)

 

Добавляем в меню.

Откройте файл commands.py в пакете utils.

Добавьте команду в меню, по аналогии с другими:

BotCommand(  
    command='weather',  
    description='Получить прогноз погоды'  
),

 

Завершение.

Поздравляю. Теперь ваш бот умеет сообщать прогноз погоды.
Как я и говорил в начале, добавление функционала погоды, достаточно простое. Также оно служит "примером" использования бота для получения каких-либо данных по API.

Автор

    Нет комментариев

    Реклама