Рубрики
Без рубрики

Как получить Messenger Facebook, чтобы уведомить вас о погоде

Автор оригинала: Ekapope Viriyakovithya.

Полное подеение руководства по созданию собственного боевого бота погоды.

Утренняя рутина всегда стресса. Разве это не было бы замечательно, если у вас было меньше всего беспокоиться утром?

Что, если у вас была настраиваемая погода Bott Bot, который отправил вам короткое сообщение, только когда появился дождь над вашим заранее определенным порогом?

Не тратьте время, проверяя погоду в отдельном приложении. Может быть жить на вашем Messenger Chatbox!

Что вам нужно?

  • Python 3.6 (или раньше) с пандами и fbchat Установлены пакеты
pip install fbchat
  • Accuweather Developer учетной записи Свободный пакет должен быть достаточно. Он обеспечивает 50 звонков в день с 1 ключевой учетной записью/разработчиком.

Давайте начнем!

В конце этого, у вас будет 3 файла в папке сценариев:

Клавиши .py : Чтобы сохранить ваш почтовый адрес Facebook, пароль и ключ Accuweather API

paramspy : Для хранения порогового и прогноза прогноза погоды

main.py : Это главный скрипт, он позвонит на Keys.py и params.py

1. Настройте учетную запись Facebook и Accuweather API

Во-первых, давайте поставьте свою учетную запись в Клавиши .py файл.

# Your Facebook usersname (email)
FB_USERNAME= "" 

# Your Facebook password
FB_PASSWORD= "" 

# Your AccuWeather API key
ACCUWEATHER_API_KEY= ""

2. Настройка параметров

На этом этапе мы определим порог для вероятности вероятности дождя или снега, задержать время между каждым запросом и сообщением, а также местоположением.

В настоящее время мы устанавливаем порог на 25% как для дождя, так и на снегу. Мы получим сообщение о предупреждении только в том случае, если данные Accuweather показывают вероятность ≥ 25%.

Приведенные ниже скрипты запрошу данные от Accuweather каждые 1 час () и отправят сообщение каждые 4 часа ().

Эти параметры будут храниться в paramspy файл.

# Define % threshold for probability of rain and snow. 
# The msg will be sent out if the % chance exceed the value
RAIN_THRESHOLD = 25
SNOW_THRESHOLD = 25

# time between Accuweather request (in hour)
UPDATE_INTERVAL_HR = 1 

# delay time between msg (in hour)
DELAY_TIME_HR = 4 

# location id
# for example, https://www.accuweather.com/en/fr/lille/135564/weather-forecast/135564
# location id is 135564
LOCATION_ID = "135564" 

3. Получить данные от Accuweather

Теперь здесь приходит веселая часть. Теперь мы будем работать над главным сценарием.

Если вы планируете запустить его на месте, настройте свой каталог и импортируйте клавиши и параметры. Убедитесь, что вы поставили Клавиши .py и paramspy в той же папке, что и это main.py скрипт

#set the current directory
import os
os.chdir(r".\YOUR_PATH")
###############################################################################
#import keys and parameters other scripts in the same folder
from keys import FB_USERNAME,FB_PASSWORD,ACCUWEATHER_API_KEY
from params import RAIN_THRESHOLD,SNOW_THRESHOLD,UPDATE_INTERVAL_HR,DELAY_TIME_HR,LOCATION_ID

Импорт требуемых модулей.

#import required modules
import urllib
import urllib.parse
import json
import time
import requests
import pandas as pd
import logging
import sys
from fbchat import Client
from fbchat.models import *
from datetime import datetime

Определите «URL_Page», который будет запрошен в этом примере, мы возьмем 12-часовой почасовой прогноз. Преобразуйте наше время обновления/задержки в секунды.

url_page = "http://dataservice.accuweather.com/forecasts/v1/hourly/12hour/"+str(LOCATION_ID)+"?apikey="+ACCUWEATHER_API_KEY+"&details=true&metric=true"
#convert hours to seconds
update_interval_sec = 60*60*UPDATE_INTERVAL_HR 
delay_time_sec = 60*60*DELAY_TIME_HR 

Затем запросите данные и поместите в PandaS DataFrame под названием «JSON_DF».

На данный момент мы можем осмотреть восстановленную таблицу. Извлечь и переименуйте элементы, которые нам нужны. В этом примере нам понадобится Accuweather Link,% дождя,% снега, дата и время в желаемом формате.

    json_page = urllib.request.urlopen(url_page)
    json_data = json.loads(json_page.read().decode())
    json_df = pd.DataFrame(json_data)
    
    # set maximum width, so the links are fully shown and clickable
    pd.set_option('display.max_colwidth', -1)
    json_df['Links'] = json_df['MobileLink'].apply(lambda x: 'Link')
    
    json_df['Real Feel (degC)'] = json_df['RealFeelTemperature'].apply(lambda x: x.get('Value'))
    json_df['Weather'] = json_df['IconPhrase'] 
    json_df['Percent_Rain'] = json_df['RainProbability'] 
    json_df['Percent_Snow'] = json_df['SnowProbability'] 

Если мы посмотрим внимательно, столбец «DateTime» немного сложно извлечь и нуждается в некоторой работе. После очистки сохраните его в переменной «ustrem_retried_dateTime».

json_df[['Date','Time']] = json_df['DateTime'].str.split('T', expand=True)
# trim the time to hh:mm format, change to str
json_df[['Time']] = json_df['Time'].str.split('+', expand=True)[0].astype(str).str[:5]

current_retrieved_datetime = str(json_df['Date'][0])+' '+str(json_df['Time'][0])

Далее, напишите состояние IF-Ever, чтобы настроить сообщение о предупреждении. Восстановленная таблица предоставляет нам прогноз 12 часов. Мы проверим каждый элемент под дождем, так и снегами и возвращаем сообщение, если вероятность выше порога.

Во-первых, инициализируйте сообщение о предупреждении для каждого случая.

rain_msg=""
snow_msg=""

Проверьте столбцы «Процентірейн» и «проценты_snow», флаг с 1, если вероятность% приведена выше пороговое значение (или 0 в противном случае).

Суммируйте столбцы и измените «RAIN_MSG» и «SNOW_MSG».

    # check % Rain column, return rain_msg
    json_df.loc[json_df['Percent_Rain'] >= RAIN_THRESHOLD, 'Rain_Alert'] = 1  
    json_df.loc[json_df['Percent_Rain'] < RAIN_THRESHOLD, 'Rain_Alert'] = 0
    if (sum(json_df['Rain_Alert']) > 0):
        rain_msg = 'There is ' \
                    +str(json_df['Percent_Rain'][json_df['Rain_Alert']==1][0]) \
                    +' % chance of rain' \
                    +' at ' \
                    +str(json_df['Time'][json_df['Rain_Alert']==1][0])
    
    # check % Snow column
    json_df.loc[json_df['Percent_Snow'] >= SNOW_THRESHOLD, 'Snow_Alert'] = 1  
    json_df.loc[json_df['Percent_Snow'] < SNOW_THRESHOLD, 'Snow_Alert'] = 0
    if (sum(json_df['Snow_Alert']) > 0):
        snow_msg = 'There is ' \
                    +str(json_df['Percent_Snow'][json_df['Percent_Snow']==1][0]) \
                    +' % chance of snow' \
                    +' at ' \
                    +str(json_df['Time'][json_df['Percent_Snow']==1][0])

Инициализируйте «ALERT_MSG», измените сообщения, если есть какой-либо «RAIN_MSG» или «Snow_Msg».

alert_msg =""
if(len(rain_msg)|len(snow_msg)!=0):
     alert_msg = rain_msg +" "+snow_msg

Добавьте ссылку на переменную «Link_for_Click», это будет прикреплена к сообщению, когда мы отправим позже.

link_for_click = json_df['MobileLink'][0]

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

def func_get_weather(url_page):

    json_page = urllib.request.urlopen(url_page)
    json_data = json.loads(json_page.read().decode())
    json_df = pd.DataFrame(json_data)
    
    # set maximum width, so the links are fully shown and clickable
    pd.set_option('display.max_colwidth', -1)
    json_df['Links'] = json_df['MobileLink'].apply(lambda x: 'Link')
    
    json_df['Real Feel (degC)'] = json_df['RealFeelTemperature'].apply(lambda x: x.get('Value'))
    json_df['Weather'] = json_df['IconPhrase'] 
    json_df['Percent_Rain'] = json_df['RainProbability'] 
    json_df['Percent_Snow'] = json_df['SnowProbability'] 
    json_df[['Date','Time']] = json_df['DateTime'].str.split('T', expand=True)
    # trim the time to hh:mm format, change to str
    json_df[['Time']] = json_df['Time'].str.split('+', expand=True)[0].astype(str).str[:5]
    
    current_retrieved_datetime = str(json_df['Date'][0])+' '+str(json_df['Time'][0])
    
    rain_msg=""
    snow_msg=""
    
    # check % Rain column, return rain_msg
    json_df.loc[json_df['Percent_Rain'] >= RAIN_THRESHOLD, 'Rain_Alert'] = 1  
    json_df.loc[json_df['Percent_Rain'] < RAIN_THRESHOLD, 'Rain_Alert'] = 0
    if (sum(json_df['Rain_Alert']) > 0):
        rain_msg = 'There is ' \
                    +str(json_df['Percent_Rain'][json_df['Rain_Alert']==1][0]) \
                    +' % chance of rain' \
                    +' at ' \
                    +str(json_df['Time'][json_df['Rain_Alert']==1][0])
    
    # check % Snow column
    json_df.loc[json_df['Percent_Snow'] >= SNOW_THRESHOLD, 'Snow_Alert'] = 1  
    json_df.loc[json_df['Percent_Snow'] < SNOW_THRESHOLD, 'Snow_Alert'] = 0
    if (sum(json_df['Snow_Alert']) > 0):
        snow_msg = 'There is ' \
                    +str(json_df['Percent_Snow'][json_df['Percent_Snow']==1][0]) \
                    +' % chance of snow' \
                    +' at ' \
                    +str(json_df['Time'][json_df['Percent_Snow']==1][0])

    alert_msg =""
    if(len(rain_msg)|len(snow_msg)!=0):
         alert_msg = rain_msg +" "+snow_msg
    
    link_for_click = json_df['MobileLink'][0]
    
    return(current_retrieved_datetime,alert_msg,link_for_click)

4. Автоматизированная петля

Наконец, для последней части мы автоматизируем процесс с помощью петлей. Приведенные ниже скрипты помещают количество петель как «.

num_repeat = 999 # number of loops to repeat
previous_alert_msg = "" # initialize alert msg

Используйте попытку, кроме преодоления ошибок (на случай, если что-то пойдет не так с подключениями). Вызовите функцию func_get_weather и назначить переменные.

for i in range(num_repeat):
    try:
        current_retrieved_datetime,alert_msg,link_for_click = func_get_weather(url_page)
    except (RuntimeError, TypeError, NameError, ValueError, urllib.error.URLError):
        print('error catched')

Затем проверьте, есть ли какие-либо изменения в погоде. Если ничего не изменилось, распечатайте сообщение на экран. Не будет отправлено сообщение об чате.

    #if the weather forecast has not changed, no alert msg will be sent
    if len(alert_msg) > 0 and previous_alert_msg == alert_msg:
        print(i, current_retrieved_datetime, 'no changes in weather forecast')

Сообщение будет отправлено только в том случае, если есть какие-либо изменения в погоде.

Мы можем доработать наше сообщение в этот момент. Получить свой идентификатор пользователя своих друзей и храните в «Friend_List». Цикл, чтобы отправить сообщение каждому другу односторонню. Мы помещаем секунды сна между каждым сообщением и выходом после завершения.

    if len(alert_msg) > 0 and previous_alert_msg != alert_msg:    
        # login and send facebook msg 
        client = Client(FB_USERNAME,FB_PASSWORD)
        users = client.fetchAllUsers()
        friend_list=[user.uid for user in users if user.uid!="0"]
        # loop though all friends
        for id in friend_list: 
            client.send(Message(text=current_retrieved_datetime+' '+'12-hr Weather Forecast' +' '+ alert_msg +' '+link_for_click),thread_id=id, thread_type=ThreadType.USER)
            #sleep for 2 secs between each msg
            time.sleep(2) 
        #logout after sent
        client.logout()   

Выполните время задержки для следующего сообщения. Уже определено в paramspy Файл – в этом случае это 4 часа. И еще один для задержки запроса на Accuweather составляет 1 час.

    time.sleep(delay_time_sec)                         
time.sleep(update_interval_sec)

Опять же, не волнуйтесь, если вы потерялись. Я поставил полный цикл вместе ниже.

# Execute functions, retrieve data and send facebook msg
num_repeat = 999 # number of loops to repeat
previous_alert_msg = "" # initialize alert msg
for i in range(num_repeat):
    
    try:
        current_retrieved_datetime,alert_msg,link_for_click = func_get_weather(url_page)
    except (RuntimeError, TypeError, NameError, ValueError, urllib.error.URLError):
        print('error catched')

    #if the weather forecast has not changed, no alert msg will be sent
    if len(alert_msg) > 0 and previous_alert_msg == alert_msg:
        print(i, current_retrieved_datetime, 'no changes in weather forecast')
    #if there is any changes in weather       
    if len(alert_msg) > 0 and previous_alert_msg != alert_msg:    
        # login and send facebook msg 
        client = Client(FB_USERNAME,FB_PASSWORD)
        users = client.fetchAllUsers()
        friend_list=[user.uid for user in users if user.uid!="0"]
        # loop though all friends
        for id in friend_list: 
            client.send(Message(text=current_retrieved_datetime+' '+'12-hr Weather Forecast' +' '+ alert_msg +' '+link_for_click),thread_id=id, thread_type=ThreadType.USER)
            #sleep for 2 secs between each msg
            time.sleep(2) 
        #logout after sent
        client.logout()    
        time.sleep(delay_time_sec)                         
    time.sleep(update_interval_sec)
print(current_retrieved_datetime,'Run Completed')

Та-да! После всей нашей тяжелой работы, вот снимок сообщения, которое мы получим.

Если нам нужно знать более подробно, мы можем напрямую щелкнуть по ссылке. Он будет переходить на мобильный веб-сайт Accuweather.

Заполненный скрипт для этого как – это тоже Документировано на Github Отказ

Спасибо за чтение. Пожалуйста, попробуйте, повеселиться и дайте мне знать ваши отзывы!

Если вам понравится то, что я сделал, подумайте о том, чтобы следовать за мной Github , Средний и Twitter Отказ Убедитесь, что чтобы звездить на Github : D.