Le gouvernement métropolitain de Tokyo publie chaque jour le nombre de personnes positives pour le nouveau virus corona (COVID-19) à Tokyo. Je voulais publier automatiquement ces données sur Slack, j'ai donc créé le code source.
[Site métropolitain de contrôle des maladies infectieuses du nouveau virus Corona de Tokyo] 1 les données sont acquises, organisées, tracées et publiées sur Slack.
Il est nécessaire de préparer le Token de Slackbot à l'avance, mais dans cet article, nous omettons la méthode d'émission du Token.
J'ai implémenté un bot pour publier du contenu sur Slack en exécutant python3 run.py
.
Le contenu de run.py
est comme ça.
import plot
import post
def main():
df = plot.fetch_csv() #L'acquisition des données
plot.plot_hist(df) #Dessin graphique
txt = plot.info_str(df) #Dernier décompte positif
post.post_message(txt) #Publiez le dernier nombre de positifs
post.upload_figure("", "") #Post graphique
if __name__ == "__main__":
main()
J'ai préparé post.py
et plot.py
dans le même répertoire que run.py
.
C'est le processus de plot.fetch_csv ()
.
[Les données publiques de Tokyo] 2 ont été acquises.
import requests
import pandas as pd
URL = "https://stopcovid19.metro.tokyo.lg.jp/"
def fetch_csv():
r = requests.get(URL+"data/130001_tokyo_covid19_patients.csv")
df = pd.read_csv(io.BytesIO(r.content),sep=",")
return df
C'est le processus de plot.plot_hist (df)
.
Dessinez un histogramme avec des pandas en utilisant les données acquises.
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
PNG = "hist"
def plot_hist(df):
#Extraire uniquement les colonnes de date avec horodatage
df = pd.to_datetime(df.loc[:, "Publié_Date"])
# bins(Nombre total de jours)Calculer
num_bins = calc_num_days(df)
#Divisé de haut en bas
fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True)
df.hist(ax=axes[0], bins=num_bins)
axes[0].set_title("De jour", fontproperties=FP)
df.hist(ax=axes[1], bins=num_bins, cumulative=True)
plt.title("Accumulation", fontproperties=FP)
plt.suptitle("Tokyo COVID-19 Nombre de positifs(La source de données"+URL+")", fontproperties=FP)
#Définir la taille de pas de l'axe des x sur 1 semaine
plt.gca().get_xaxis().set_major_formatter(mdates.DateFormatter("%y/%m/%d"))
plt.gca().get_xaxis().set_major_locator(mdates.DayLocator(interval=7))
plt.xticks(rotation=90) #Faire pivoter l'étiquette de l'axe x de 90 degrés
plt.savefig(PNG, bbox_inches="tight")
calc_num_days (df)
est utilisé pour calculer les cases de l'histogramme.
Dans les données acquises (csv), la première ligne à l'exclusion de la ligne d'en-tête correspond aux données du patient le jour où le nombre de positifs a été confirmé pour la première fois, et la dernière ligne correspond aux dernières données du patient.
def calc_num_days(df):
s = df.iloc[0] #1ère ligne, 1ère colonne
e = df.iloc[-1] #Première colonne de la dernière ligne
delta_days = e - s
return delta_days.days + 1
Puisque la police japonaise est utilisée pour le titre du graphique, fontproperties
est spécifié comme plt.title (" cumulative ", fontproperties = FP)
.
FONT_TTF = "/home/[Nom d'utilisateur]/.local/lib/python3.5/site-packages/matplotlib/mpl-data/fonts/ttf/ipaexg.ttf"
FP = FontProperties(fname=FONT_TTF)
Selon l'environnement, vous pouvez utiliser des polices japonaises sans spécifier de propriétés de police
.
Au fait, je voulais à l'origine dessiner avec un graphique à barres au lieu d'un histogramme, mais cela n'a pas fonctionné. Le point qui n'a pas fonctionné était que l'axe horizontal était traité comme une étiquette au lieu de l'axe du temps, et le jour où le nombre de positifs était de 0 n'a pas pu être bien dessiné. J'ai pensé qu'il serait préférable de créer une étiquette pour le jour où le nombre de personnes positives était de 0, mais j'ai pensé qu'il serait plus facile de le dessiner sous forme d'histogramme, alors je l'ai dessiné avec un histogramme. Je vous serais reconnaissant de bien vouloir me dire s’il existe un moyen plus intelligent.
C'est un processus avec plot.info_str (df)
.
Je crée le texte que je souhaite publier sur Slack à partir des données.
def info_str(df):
#Extraire uniquement les colonnes de date
df = df.loc[:, "Publié_Date"]
today = df.iloc[-1] #Première colonne de la dernière ligne
# index:Date, colums:Nombre de personnes
df = df.value_counts().sort_index()
num_y = int(df.iloc[-2]) # yesterday
num_t = int(df.iloc[-1]) # today
txt = today+"Personne positive à l'époque:"+str(num_t)+"Homme\n" \
+"(Par rapport à hier:"+str(num_t - num_y)+"Homme,Total"+str(df.sum())+"Homme)\n" \
+ URL
return txt
C'est le traitement de post.post_message (txt)
.
↑ Je publierai ceci sur Slack.
Utilisez le module slackbot de Python et l'API Slack.
import json
import requests
SLACK_API = "https://slack.com/api/"
TITLE = "COVID-19 Nombre de personnes positives à Tokyo"
def post_message(txt, title=TITLE):
API_METHOD = "chat.postMessage"
response = requests.post(SLACK_API + API_METHOD, data={
"token": SLACK_TOKEN,
"channel": SLACK_CHANNEL,
"username": USER_NAME,
"as_user": True,
"attachments": json.dumps([
{
"fallback": title,
"color": "#00FFFF",
"title": title,
"text": txt,
}
])
}).json()
Décrivez le jeton de Slackbot dans SLACK_TOKEN
.
Décrivez le nom du canal (" # hogehuga "
) dans SLACK_CHANNEL
.
ʻUSER_NAME` décrit le nom d'utilisateur du bot.
C'est le processus de post.upload_figure (" "," ")
.
↑ Je publierai cette image sur Slack.
PNG = "hist"
PNG_FILE = PNG+".png "
def upload_figure(txt, title=TITLE):
files = {"file": open(PNG_FILE, "rb")}
param = {
"token": SLACK_TOKEN,
"channels": CHANNEL_ID,
"filename": PNG_FILE,
"initial_comment": title+"\n"+txt,
"title": title
}
requests.post(url=SLACK_API+"files.upload", params=param, files=files)
CHANNEL_ID
est identique à la chaîne à la fin de l'URL de la chaîne. Ce n'est pas un nom de chaîne.
Si le terminal (serveur) est toujours en cours d'exécution, vous pouvez exécuter des commandes régulièrement en utilisant crontab.
Par exemple, si vous voulez publier automatiquement à 15h05 tous les jours, ouvrez l'éditeur avec crontab -e
et écrivez ce qui suit.
05 15 * * * cd [Répertoire avec code source]; python3 run.py >run.log
Nous avons acquis le nombre de positifs pour le nouveau virus corona à Tokyo et avons créé un bot à publier sur Slack.
En ce qui concerne les futurs numéros, j'aimerais être en mesure de notifier automatiquement lorsque [Tokyo data] 2 est mis à jour. Si vous trouvez une bonne méthode, j'aimerais l'essayer.
Recommended Posts