[PYTHON] J'ai automatiquement collecté mes données de publication Qiita avec Raspberry Pi et je les ai régulièrement notifiées avec Slack

introduction

J'ai récemment publié plusieurs articles, mais je voulais voir des données telles que le nombre total de vues jusqu'à présent, j'ai donc créé un environnement avec Raspeye. Cette fois, l'objectif est d'acquérir des données régulièrement avec Raspeye, de créer un graphique une fois par jour et de l'envoyer automatiquement à Slack.

environnement

L'environnement de Mac qui se développe principalement est le suivant.

$sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G9016

La tarte aux râpes utilisée est le Raspberry Pi 3 Model B. Le système d'exploitation est le suivant.

$ cat /etc/os-release 
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=raspbian
ID_LIKE=debian
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"

Construire

Je n'ai pas utilisé Raspeye depuis un certain temps, mais lorsque j'ai essayé de l'utiliser à nouveau, je n'ai pas pu me connecter, et lorsque j'ai essayé de changer le mot de passe, le système d'exploitation a cessé de démarrer, alors j'ai commencé par réinstaller le système d'exploitation. Après cela, installez les bibliothèques et les outils nécessaires et créez MySQL (MariaDB) qui stocke les données Qiita. Enfin, nous allons créer un processus qui envoie périodiquement à Slack.

Réinstallation du système d'exploitation Raspberry Pi

Cliquez ici pour réinstaller le système d'exploitation Vous pouvez maintenant démarrer le système d'exploitation en l'exécutant comme décrit dans [^ 1]. La procédure est exactement comme décrit, donc je vais l'omettre.

Un problème est survenu à cause du fait que «apt update» n'a pu être exécuté avec une erreur. Après essais et erreurs, comme décrit ici [^ 2],

sudo dhclient eth0

Cela a résolu le problème. Après cela, exécutez la commande suivante.

sudo apt-get update
sudo apt-get upgrade

Configuration de la base de données

Ensuite, créez une base de données qui stocke des données telles que le nombre de vues de Qiita. Cette fois, j'utiliserai MySQL. Mais quand j'ai essayé d'installer MySQL

$ sudo apt-get install mysql-server
Chargement de la liste des packages...Terminé
Créer une arborescence de dépendances
Lecture des informations d'état...Terminé
Paquet mysql-serveur n'est pas disponible, mais est référencé par un autre package.
Il s'agit d'un package manquant, obsolète ou d'une autre source
Cela signifie qu'il n'est disponible qu'à partir de.
Mais les packages suivants remplacent:
  mariadb-server-10.0

E:paquet'mysql-server'N'a pas de candidats à l'installation

Une erreur s'est affichée et l'installation n'a pas pu être effectuée. Cependant, dans le message d'erreur, il est affiché que MariaDB sera remplacée, donc quand je l'ai essayé, J'ai pu l'installer avec la commande suivante.

sudo apt-get install mariadb-client mariadb-server

Cette fois, je pense mettre le japonais dans les données, je vais donc définir la langue. En référence à ceci [^ 3], j'ai modifié / etc / mysql / conf.d / mysql.cnf comme suit.

/etc/mysql/conf.d/mysql.cnf


[mysql]
default-character-set=utf8mb4

Redémarrez MySQL et configurez les paramètres de l'utilisateur et de la base de données.

$ sudo service mysql restart
$ sudo mysql -u root -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 60
Server version: 10.3.17-MariaDB-0+deb10u1 Raspbian 10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE DATABASE myqiita;
MariaDB [(none)]> CREATE USER 'pi'@'localhost' IDENTIFIED BY '<mot de passe>';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON myqiita.* to 'pi'@'localhost';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| myqiita            |
+--------------------+
2 rows in set (0.002 sec)

MariaDB [(none)]> quit
Bye

Vous êtes maintenant prêt à vous connecter en tant qu'utilisateur pi et à stocker vos données dans la base de données myqiita.

Création de scripts d'acquisition de données

Écrivez le code lié à la connexion à la base de données que vous avez définie précédemment.

myconnection.py


import MySQLdb
import pandas.io.sql as psql

class myDB():

    def __init__(self):
        self.connection = MySQLdb.connect(
            host='localhost',
            user='pi',
            passwd='<mot de passe>',
            charset='utf8',
            db='myqiita')
        self.cursor = self.connection.cursor()

    def exe(self, sql):
        self.cursor.execute(sql)
        return self.cursor.fetchall()

    def exedf(self, sql):
        return psql.read_sql(sql, self.connection)

    def commit(self):
        self.connection.commit()

    def close(self):
        self.connection.close()

La partie décrite comme `` '' est le mot de passe lorsque l'utilisateur pi a été créé dans MySQL.

Exécutez le programme suivant pour créer une table mytable pour stocker les données. En outre, il existe une partie textuelle sur la spécification de type de chaque colonne.

create.py


import MySQLdb
from myconnection import myDB

if __name__ == '__main__':
    
    mydb = myDB()

    sql = """
    create table mytable( 
    id int(11) AUTO_INCREMENT NOT NULL,
    create_datetime datetime not null default current_timestamp,
    tot_num_articles int(11) not null,
    tot_num_views int(11) not null,
    tot_num_likes int(11) not null,
    max_num_views int(11) not null,
    max_num_views_title varchar(100) not null,
    max_num_likes int(11) not null,
    max_num_likes_title varchar(100) not null,
    PRIMARY KEY (id))
    """
    print( sql )
    mydb.exe( sql )

Ensuite, créez le code pour obtenir les données de Qiita et les stocker dans la base de données.

insert.py


import requests
import json
import datetime
import MySQLdb
from myconnection import myDB

def collection():

    dt_now = datetime.datetime.now()

    url = 'https://qiita.com/api/v2/authenticated_user/items'
    headers = {"content-type": "application/json",
               "Authorization": <Jeton d'accès>}
    
    res = requests.get(url, headers=headers)
    article_list = res.json()

    tot_num_articles = len(article_list)
    tot_num_views = 0
    tot_num_likes = 0
    max_num_views = 0
    max_num_likes = 0
    max_num_views_title = ''
    max_num_likes_title = ''

    
    for item in article_list:
        item_id = item['id']
        title = item['title']
        likes_count = item['likes_count']
    
        url = 'https://qiita.com/api/v2/items/' + item_id
        res = requests.get(url, headers=headers)
        json = res.json()
        page_views_count = json['page_views_count']
    
        tot_num_views += page_views_count
        tot_num_likes += likes_count

        if max_num_views < page_views_count:
            max_num_views = page_views_count
            max_num_views_title = title

        if max_num_likes < likes_count:
            max_num_likes = likes_count
            max_num_likes_title = title

    data={'dt':dt_now, 
            'tot_num_articles':tot_num_articles, 
            'tot_num_views':tot_num_views, 
            'tot_num_likes':tot_num_likes, 
            'max_num_views':max_num_views, 
            'max_num_views_title':max_num_views_title, 
            'max_num_likes':max_num_likes, 
            'max_num_likes_title':max_num_likes_title}
    return data
    

if __name__ == '__main__':
    
    mydb = myDB()

    data = collection()

    sql = """
    insert into mytable 
    (tot_num_articles,tot_num_views,tot_num_likes,max_num_views,max_num_views_title,max_num_likes,max_num_likes_title)
    values({},{},{},{},"{}",{},"{}")
    """.format(data['tot_num_articles'],
            data['tot_num_views'],
            data['tot_num_likes'], 
            data['max_num_views'], 
            data['max_num_views_title'], 
            data['max_num_likes'], 
            data['max_num_likes_title'])
    print(sql)
    mydb.exe(sql)
    mydb.commit()
    mydb.close()

J'obtiens des données en accédant à l'API de Qiita dans `` collection () ''. Pour plus d'informations sur la façon d'obtenir des jetons d'accès et des données, reportez-vous ici [^ 4].

Dans la fonction principale, insérez dans la table de données mytable obtenue par `` collection () '' et validez.

Exécution périodique avec cron

Enregistrez le fichier insert.py créé précédemment dans cron pour l'exécuter régulièrement.

sudo vim /etc/cron.d/cron_test 

En créant un fichier appelé cron_test et en écrivant ce qui suit, insert.py sera exécuté à 00:00 toutes les heures.

00 *	* * *	pi	/usr/bin/python3 /home/pi/work/insert.py   

Redémarrez cron.

sudo service cron restart

Avec ce qui précède, nous avons atteint le point où les données sont acquises régulièrement.

Abonnement à Slack

Enfin, définissez les données à représenter graphiquement et à envoyer à Slack une fois par jour. Le programme est le suivant.

slack_report.py


from slacker import Slacker
import monitor

def main():
    monitor.report()
    
    slack = Slacker("<jeton>")
    slack.files.upload(file_='out_monitor.png', channels='myqiita')

if __name__ == "__main__":
    main()

Le premier est `` monitor.report () '', mais dans un autre programme appelé monitor.py, nous obtenons les données de la base de données, créons un graphique et l'enregistrons sous out_monitor.png. J'envoie ce fichier PNG à ma chaîne dans Slack. Pour la partie transmission, je me suis référé ici [^ 5].

Le contenu du programme de monitor.py est le suivant.

monitor.py


import MySQLdb
from myconnection import myDB
import pandas as pd
import matplotlib.pyplot as plt

def report():
    mydb = myDB()

    sql = """
    select * from mytable
    """
    df = mydb.exedf( sql )

    # Preprocess
    df['create_datetime'] = pd.to_datetime(df['create_datetime'])
    df = df.set_index('create_datetime')

    # Plot
    fig = plt.figure()
    ax1 = fig.add_subplot(311)
    df['tot_num_articles'].plot(ax=ax1)
    ax1.set_xticklabels('')
    ax1.set_xlabel('')
    ax1.set_ylabel('tot_num_articles')
    ax1.grid()
    ax2 = fig.add_subplot(312)
    df['tot_num_views'].plot(ax=ax2)
    ax2.set_xticklabels('')
    ax2.set_xlabel('')
    ax2.set_ylabel('tot_num_views')
    ax2.grid()
    ax3 = fig.add_subplot(313)
    df['tot_num_likes'].plot(ax=ax3)
    ax3.set_ylabel('tot_num_likes')
    ax3.grid()
    fig.savefig('out_monitor.png')

if __name__ == '__main__':
    report()

Toutes les données stockées dans la table myqiita sont acquises, transformées en un DataFrame de pandas, puis représentées graphiquement. Veuillez consulter ici [^ 6] pour la conversion en DataFrame. Les éléments du graphique sont le nombre de vos articles, le nombre total de vues et le nombre total de likes.

Enregistrez le programme dans cron pour que slack_report.py soit exécuté régulièrement. Le contenu de cron_test est affiché ci-dessous.

/etc/cron.d/cron_test


# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
00 *	* * *	pi	/usr/bin/python3 /home/pi/work/insert.py   
10 8	* * *	pi	/usr/bin/python3 /home/pi/work/slack_report.py 

Enfin, redémarrez cron.

sudo service cron restart

résultat

Voici une capture d'écran envoyée à Slack sur mon smartphone.

7F3D2229-9000-4AEC-A4E7-AF27B797E7D5.png

Les graphiques sont désormais envoyés tous les matins à 8h10. Bien.

à la fin

Vous pouvez désormais envoyer régulièrement des données de navigation Qiita à Slack avec Raspeye. C'est intéressant car lorsque vous pouvez voir les données, vous remarquerez que l'augmentation du nombre de vues varie en fonction de l'heure de la journée. Le nombre de vues et de likes est encore faible, mais ...

Recommended Posts

J'ai automatiquement collecté mes données de publication Qiita avec Raspberry Pi et je les ai régulièrement notifiées avec Slack
[Pour les débutants] J'ai fait un capteur humain avec Raspberry Pi et notifié LINE!
J'ai essayé de connecter Raspeye et conect + avec l'API Web
Mesurez et comparez les températures avec Raspberry Pi et générez automatiquement des graphiques
J'ai fait une caméra de surveillance avec Raspberry PI pour la première fois.
Home Hack pour acheter automatiquement quand il devient moins cher avec Amazon Dash Button et Raspberry Pi
Créez un thermomètre avec Raspberry Pi et rendez-le visible sur le navigateur Partie 4
Lisez les données du lecteur NFC connecté à Raspberry Pi 3 avec Python et envoyez-les à openFrameworks avec OSC
Acquérir la valeur du capteur de Grove Pi + avec Raspberry Pi et la stocker dans Kintone
Surveillance des animaux avec Rekognition et Raspberry pi
J'ai créé un système avec Raspberry Pi qui mesure périodiquement l'indice d'inconfort de la pièce et envoie une notification LINE s'il s'agit d'une valeur dangereuse
Fabriquez un thermomètre avec Raspberry Pi et rendez-le visible sur le navigateur Partie 3
J'ai essayé de créer un bouton pour Slack avec Raspeye + Tact Switch
Générer et publier des données d'image factice avec Django
MQTT Radicon Car avec Arduino et Raspberry
Sortie CSV des données d'impulsion avec Raspberry Pi (sortie CSV)
Obtenez la température et l'humidité avec DHT11 et Raspberry Pi
J'ai créé et publié une image Docker qui lit RSS et tweete automatiquement régulièrement.
Il fait froid, j'ai donc essayé de permettre d'allumer / d'éteindre automatiquement le chauffage AC avec Raspberry Pi!