[PYTHON] J'ai créé un SlackBot qui m'informe chaque semaine des informations sur le concours AtCoder

Informations sur le concours AtCoder Nous avons créé un Slackbot pour notifier les informations sur le concours AtCoder.

(1) Obtention du jeton de l'API Bot et installation de slackbot

Vous devez obtenir un jeton API et installer slackbot avant de pouvoir créer un Slackbot. Ces deux éléments sont décrits dans Développement SlackBot avec Python ① "Obtenir la clé API et la réponse simple" Je viens de faire ça. Si vous exécutez comme écrit et envoyez une chaîne de caractères appropriée en conversation avec Bot, le libellé défini dans DEFALUT_REPLY sera renvoyé comme indiqué ci-dessous. スクリーンショット 2019-11-13 16.13.20.png

(2) Grattage Web

Depuis que j'ai confirmé que Slackbot fonctionne, je vais gratter et collecter les informations du concours AtCoder. Ci-dessous le code.

scrape.py



from urllib import request
from bs4 import BeautifulSoup
import re
import datetime


#Renvoie une paire heure / URL
def scrape_active():
    '''
Une fonction qui renvoie des informations sur le concours en cours
    '''
    re_contests=[]
    #Recevoir des informations sur cette URL
    url="https://atcoder.jp"
    html=request.urlopen(url)
    #Analyser les informations de la page avec un analyseur
    soup=BeautifulSoup(html, "html.parser")
    #contest-table-Les informations sur le concours en cours sont incluses dans la balise div avec l'identifiant d'actif
    contests1=soup.find("div",id="contest-table-active")
    #S'il n'y a pas de concours(Parce qu'aucun ne sera inclus dans la soupe)
    if contests1 is None:
        return re_contests
    contests2=contests1.find("tbody")
    contests3=contests2.find_all("tr")
    #re_Enregistrer l'URL du concours et la date et l'heure de fin des concours
    for c in contests3:
        re_contests_sub=[]
        #Stocker l'url de la page du concours dans url2
        d=c.find("a",href=re.compile("contests"))
        url2=url+d.get("href")
        html2=request.urlopen(url2)
        soup2=BeautifulSoup(html2, "html.parser")
        #class est un mot réservé en Python, donc class_
        sftime=soup2.find_all("time",class_="fixtime-full")
        #Re seulement le temps de la fin_contests_Stocker en sous
        re_contests_sub.append(sftime[1]+"Fin")
        #L'url de la page du concours est également re_contests_Stocker en sous
        re_contests_sub.append(url2)
        re_contests.append(re_contests_sub)
    return re_contests


def scrape_upcoming():
    '''
Une fonction qui renvoie des informations sur les concours organisés dans une semaine
    '''
    re_contests=[]
    url="https://atcoder.jp"
    html = request.urlopen(url)
    soup = BeautifulSoup(html, "html.parser")
    #contest-table-Les informations sur les concours qui auront lieu dans une semaine sont incluses dans la balise div avec l'identifiant du prochain
    contests1=soup.find("div",id="contest-table-upcoming")
    #S'il n'y a pas de concours(Parce qu'aucun ne sera inclus dans la soupe)
    if contests1 is None:
        return re_contests
    contests2=contests1.find("tbody")
    contests3=contests2.find_all("tr")
    #Obtenir la date et l'heure du jour(Lundi)
    w=datetime.datetime.today()
    #Re l'url et la date et l'heure de début du concours_Stocker dans les concours
    for c in contests3:
        re_contests_sub=[]
        d1=c.find("time")
        #Trancher et passer uniquement la partie qui contient jusqu'à la minute
        #Retour d'une chaîne à un objet datetime avec la fonction strtotime
        t=strtotime(d1.text[:16])
        #Vous n'avez pas à stocker les concours qui ne sont pas le dimanche de la semaine
        if (t-w).days>=7:
            break
        #Utilisez la fonction timeostr pour unifier le format
        #Stocker la date et l'heure de début du concours
        re_contests_sub.append(timetostr(t)+"début")
        d2=c.find("a",href=re.compile("contests"))
        #L'url de la page du concours est également re_contests_Stocker en sous
        re_contests_sub.append(url+d2.get("href"))
        re_contests.append(re_contests_sub)
    return re_contests

def strtotime(date_sub):
    '''
Retour en tant qu'objet datetime
    '''
    return datetime.datetime.strptime(date_sub,'%Y-%m-%d %H:%M')

def timetostr(date_sub):
    '''
Renvoie un objet datetime en tant qu'objet str
    '''
    W=["Mois","Feu","eau","bois","Argent","sol","journée"]
    return ('%d-%d-%d(%s) %d:%s'%(
        date_sub.year,date_sub.month,date_sub.day,W[date_sub.weekday()],date_sub.hour,str(date_sub.minute).ljust(2,"0")
    ))

J'ai écrit ce que je fais dans le commentaire, mais si vous avez des questions sur l'utilisation de la fonction, veuillez consulter la page à laquelle vous avez fait référence.

Page référencée

Résumé des bases du grattage à Beautiful Soup [pour les débutants] Bases de Beautiful Soup + Requests Type de date Python datetime

(3) Publication sur Slack

Nous publierons les informations collectées sur le concours sur Slack.

run.py


from slackbot.bot import Bot
from slacker import Slacker
import slackbot_settings
import scrape
import datetime

def make_message(channel,slack,s,message):
    '''
    slack.chat.post_Envoyez un message en utilisant la messagerie.
    '''
    for i in s:
        message=message+"\n"+i[0]+"\n"+i[1]+"\n"
    #pos_Vous pouvez publier sur Slack avec un message
    #Chaîne que vous souhaitez publier sur la chaîne
    #Le message que vous souhaitez publier dans le message
    #as_En définissant l'utilisateur sur True, l'URL sera développée et publiée.
    slack.chat.post_message(channel, message, as_user=True)

def info(channel,slack):
    #Grattez d'abord pour stocker les informations du concours
    s1=scrape.scrape_active()
    s2=scrape.scrape_upcoming()
    #Aucune information sur le concours(0 de longueur)Envoyez un message indiquant que le concours n'existe pas
    if len(s1)!=0:
        make_message(channel,slack,s1,"*[Liste des concours organisés]*")
    else:
        slack.chat.post_message(channel,"*Aucun concours n'est organisé*",as_user=True)
    if len(s2)!=0:
        make_message(channel,slack,s2,"*[Liste des concours de cette semaine]*")
    else:
        slack.chat.post_message(channel,"*Il n'y a pas de concours cette semaine*",as_user=True)

def main():
    #N'oubliez pas d'ajouter l'application Bot à ce canal avant d'exécuter le Bot
    channel="Pro compétitif"
    #Le jeton API est slackbot_settings.Enregistrer dans py
    slack = Slacker(slackbot_settings.API_TOKEN)
    #Confirmation que c'est lundi
    if datetime.datetime.today().weekday()==0:
        info(channel,slack)
    bot = Bot()
    bot.run()

if __name__ == "__main__":
    main()

Voir commenter comme dans (2). (Parce que cela devient long et difficile à lire si expliqué en détail)

Page référencée

chat.postMessage L'histoire selon laquelle l'URL publiée sur les Webhooks entrants de Slack n'a pas été développée Création d'un bot avec Slack API 2: publication de messages

(4) Déployer sur Heroku

Jusqu'à (3), vous devriez pouvoir l'exécuter localement en appuyant sur python run.py. Ensuite, déployez sur Heroku. (Heroku est comme un serveur gratuit) Heroku lui-même n'est pas difficile à gérer si vous le considérez comme un dépôt distant pour Git, donc si vous étudiez Git, vous devriez savoir comment l'utiliser. (Le chapitre Git de Progate est recommandé dans son ensemble.) De plus, je vais pousser le fichier vers Heroku en utilisant Git, mais comme décrit dans l'article de référence, créons trois fichiers, Procfile, requirements.txt, runtime.txt, puis push. .. (Si vous ne le créez pas, diverses erreurs seront crachées et il sera vide.)

Page référencée

Créer Slackbot en Python Notes sur la création de SlackBot avec un résident python

(5) Définition des variables d'environnement

Si vous suivez l'article mentionné dans (1), un fichier appelé slackbot_settigns doit être créé et deux variables, API_TOKEN et DEFAULT_REPLY, doivent être définies. Cependant, si cela reste tel quel, la valeur du jeton sera obtenue lorsque le code source fuit et le Bot sera détourné, il est donc nécessaire de l'utiliser comme variable d'environnement sans écrire la valeur du jeton dans le code source. Localement, vous pouvez taper la commande ʻexport environment variable name = value, mais si vous voulez définir la variable d'environnement heroku, définissez la variable d'environnement en définissant heroku config: set environment variable name = value`. Je peux le faire. Vous pouvez également définir des variables d'environnement dans Config Vars ou Settings de l'application correspondante dans Heroku. Cela vous permet de définir des variables d'environnement et la réécriture de slackbot_settigns comme indiqué ci-dessous complète les paramètres des variables d'environnement.

slackbot_settings.py


import os

#Obtenir des variables d'environnement
API_TOKEN=os.environ["API_TOKEN"]
DEFAULT_REPLY=os.environ["DEFAULT_REPLY"]

Pour savoir comment utiliser os.environ, reportez-vous à Get / Add / Overwrite / Delete Environment Variables with Python (os.environ). S'il te plait donne moi.

Page référencée

[Python] Comment déployer un programme Python sur Heroku → Il décrit également comment utiliser Heroku.

(6) Enregistrement du planificateur

Lorsque vous enregistrez enfin le planificateur, toute l'automatisation est terminée. Tout d'abord, j'ajoute un planificateur en tant que module complémentaire, mais je dois enregistrer une carte de crédit. Assurez-vous de vous inscrire à partir de la page du compte. Après vous être enregistré, vous pouvez ajouter le planificateur au module complémentaire avec $ heroku addons: create scheduler: standard, et vous pouvez ouvrir la page pour vous inscrire avec le planificateur avec heroku addons: open scheduler. Si vous appuyez sur "Ajouter un travail" sur la page ouverte, vous pouvez l'exécuter régulièrement en enregistrant l'intervalle de temps pour se déplacer et la commande que vous souhaitez exécuter. (À propos, si vous l'exécutez sans l'enregistrer dans le planificateur, il sera exécuté environ toutes les 6 heures.) De plus, dans mon cas, je voulais l'exécuter une fois par semaine, alors je l'ai changé pour qu'il s'exécute tous les jours et que le programme n'effectue le traitement souhaité qu'une fois par semaine. (En outre, veuillez noter que l'heure est exprimée en UTC, vous devez donc ajouter 9 heures à l'heure UTC pour la convertir en heure japonaise.)

Page référencée

Développement SlackBot avec Python ⑧ "Exécution périodique du programme avec Heroku Scheduler"

Recommended Posts

J'ai créé un SlackBot qui m'informe chaque semaine des informations sur le concours AtCoder
J'ai fait un bot mou qui m'informe de la température
J'ai créé un Linebot qui m'informe des sites d'évacuation à proximité sur AWS
[Atcoder] [C ++] J'ai fait un outil d'automatisation de test qui peut être utilisé pendant le concours
J'ai fait un calendrier qui met à jour automatiquement le calendrier de distribution de Vtuber
Après avoir étudié Python3, j'ai créé un Slackbot
J'ai écrit un bot Slack qui notifie les informations de retard avec AWS Lambda
J'ai créé un robot LINE qui envoie des images recommandées tous les jours à l'heure
Avec LINEBot, j'ai fait une application qui m'informe de "l'heure du bus"
[Discode Bot] J'ai essayé de créer un Bot qui me dit la valeur de race de Pokemon
En Python, j'ai créé un LINE Bot qui envoie des informations sur le pollen à partir des informations de localisation.
J'ai créé une application Twitter qui décrypte les caractères de pré-connexion avec heroku (échec)
Création d'une application Web qui mappe les informations sur les événements informatiques avec Vue et Flask
[Python / C] J'ai créé un appareil qui fait défiler sans fil l'écran d'un PC à distance.
J'ai fait un calendrier qui met à jour automatiquement le calendrier de distribution de Vtuber (édition Google Calendar)
J'ai créé une boîte de changement de seuil pour Pepper's Dialog
Une histoire qui a trébuché lorsque j'ai créé un bot de chat avec Transformer
AtCoder Beginner Contest 166 A Explication du problème "A? C" (Python3, C ++, Java)
J'ai fait une fonction pour vérifier le modèle de DCGAN
J'ai fait une putain d'application qui ne te laisse pas sauter
AtCoder Grand Contest 046: A --Takahashikun, dessin d'animation The Strider
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 1)
J'ai fait une minuterie pomodoro dure qui fonctionne avec CUI
J'ai fait une image ponctuelle de l'image d'Irasutoya. (partie 2)
J'ai créé un plug-in qui peut faire "Daruma-san tombé" avec Minecraft
J'ai fait un générateur de réseau neuronal qui fonctionne sur FPGA
J'ai essayé de créer un site qui permet de voir facilement les informations mises à jour d'Azure
J'ai créé un robot Line qui devine le sexe et l'âge d'une personne à partir de l'image
J'ai créé un bot LINE qui me dit le type et la force de Pokémon dans la région de Garal avec Heroku + Flask + PostgreSQL (Heroku Postgres)