Comme le titre l'indique, j'ai écrit un code qui réalise une recherche automatique avec python en utilisant l'API Twitter et notifie les informations obtenues avec LINE Notify.
Le nombre de personnes infectées ce jour-là est annoncé quotidiennement en lien avec l'épidémie du nouveau virus corona. Que vous ayez ou non à vous soucier du nombre, ouvrez Twitter et effectuez une recherche vers midi jusqu'au soir lorsque des informations sur le nombre de personnes infectées à Tokyo sont publiées pour vérifier les dernières nouvelles dont vous ne savez pas quand elles sortiront. J'ai l'habitude d'appeler. (Je pense personnellement que c'est le plus rapide pour vérifier les dernières nouvelles du nombre de personnes infectées sur Twitter) ➡︎ Je veux éliminer le travail de recherche sur Twitter en vain! !! C'est le motif de cette fois.
Cette implémentation est spécialisée pour le nombre de personnes infectées à Tokyo, mais il semble qu'elle puisse être appliquée de différentes manières avec un léger changement.
pip install tweepy
est correct! Pip install mecab-python3 == 0.7
et tout ce dont vous avez besoin sera installé automatiquement, ce qui peut être plus facile.Leur préparation peut en fait être la partie la plus difficile. C'est amusant de rechercher sur Google et de trouver divers outils avec "{what you want to do} python", mais lol
Les détails de l'implémentation sont expliqués ci-dessous tout en regardant le code réel.
** 1. Diverses importations ** ** 2. Créez un objet pour l'accès Twitter ** ** 3. Créez un objet pour la notification LINE ** ** 4. Créez une fonction de recherche automatique **
import requests
import datetime
import time
import pandas as pd
from IPython.display import clear_output
#Fonction pour effacer la sortie d'impression
import tweepy
import MeCab
tagger = MeCab.Tagger("-Owakati")
Le "tagger" sur la dernière ligne est l'objet utilisé lors du fractionnement de phrases avec MeCab.
Plus précisément, en utilisant tagger.parse
tagger.parse("Il fait beau aujourd'hui, n'est-ce pas")
# => 'Il fait beau aujourd'hui, n'est-ce pas\n'
tagger.parse("Il fait beau aujourd'hui, n'est-ce pas").split()
# => ['aujourd'hui', 'Est', 'Bien', 'Météo', 'est', 'Hey']
C'est comme ça. Comme nous le verrons plus tard, dans cette implémentation, split () est utilisé pour créer un type de liste et gérer les tweets.
Créez un objet qui incorpore la clé et le jeton obtenus en enregistrant l'API Twitter. Référence: "Comment utiliser Tweety ~ Partie 1 ~ [Obtenir un Tweet]"
consumer_key = "Clé obtenue ici/Entrez le jeton"
consumer_secret = "Comme ci-dessus"
access_token = "Comme ci-dessus"
access_token_secret = "Comme ci-dessus"
auth = tweepy.OAuthHandler(consumer_key,consumer_secret)
auth.set_access_token(access_token,access_token_secret)
api = tweepy.API(auth) #Je vais l'utiliser plus tard
J'ai utilisé le code de l'article que j'ai cité plus tôt, "Envoyer un message à LINE avec Python" (https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9).
class LINENotifyBot:
API_URL = 'https://notify-api.line.me/api/notify'
def __init__(self, access_token):
self.__headers = {'Authorization': 'Bearer ' + access_token}
def send(
self, message,
image=None, sticker_package_id=None, sticker_id=None,
):
payload = {
'message': message,
'stickerPackageId': sticker_package_id,
'stickerId': sticker_id,
}
files = {}
if image != None:
files = {'imageFile': open(image, 'rb')}
r = requests.post(
LINENotifyBot.API_URL,
headers=self.__headers,
data=payload,
files=files,
)
access_toke_Notify = "Entrez le jeton ici"
bot_Notify = LINENotifyBot(access_token=access_token_Notify)
Maintenant, si vous faites bot_Notify.send (message =" xxxxx ")
, LINE sera livré à la destination spécifiée du jeton.
L'idée de base est
--Un certain nombre des derniers tweets contenant les mots-clés "Tokyo, infection, {date} jour" sont extraits. --S'il y a une expression «n personnes», obtenez que n
C'est comme répéter ce processus à intervalles réguliers.
Voici donc la dernière fonction ** auto_search ** à exécuter.
def auto_search(item=100,wait_time=60,rate=0.5):
"""
item:Nombre de tweets à récupérer
wait_time:Intervalle de temps pour la recherche automatique Unité s
rate:Pourcentage de tweets contenant le nombre estimé de personnes infectées
"""
d = datetime.datetime.now().day
m = datetime.datetime.now().month
print("searching on Twitter...")
pre_mode = 0 #Variables d'enregistrement des nombres qui dépassaient auparavant le taux
while True:
df = find_infected_num(d,item) # "n personnes"Une fonction qui renvoie n du type DataFrame
num_mode = df.mode().values[0,0] #Valeur la plus fréquente de df=Obtenez des candidats pour le nombre de personnes infectées
count = df.groupby("num").size() #Données agrégées du nombre de tweets par n
#num_La fréquence d'apparition du mode dépasse le taux et le nombre_le mode est une nouvelle apparence
if count.max() > item*rate and num_mode!=pre_mode:
#Sortie de résultat
print("\n--RESULT--")
print(count)
#Notification LINE des résultats
text = "{}Mois{}journée\n Personnes infectées à Tokyo[{}]Homme\n * Le ratio de tweets est{:.2f}%".format(m,d,num_mode,count.max()/item*100)
bot_Notify.send(message=text) #Envoyer à LINE
#Branchement conditionnel pour permettre la poursuite si le résultat est inapproprié
if input("\ncontinue? y/n ")=="n":
break #Fin
waiting(2,wait_time,count) #Pour affichage pendant le temps d'attente
#pre_mise à jour du mode
if count.max() > item*rate:
pre_mode = num_mode
** find_infected_num ** est une fonction pour renvoyer n sur "n personnes" dans DataFrame. Ici, le tagger préparé en 1 et l'api préparé en 2 sont utilisés.
def find_infected_num(d,item):
num_list = [] #Liste à stocker n
for tweet in tweepy.Cursor(api.search, q=['infection',"Tokyo","{}journée".format(d)]).items(item):
split_tweet = tagger.parse(tweet.text).split()
if "Homme" in split_tweet:
index = split_tweet.index("Homme") - 1
n = cut_number(split_tweet,index) # "Homme"Fonction qui renvoie le nombre immédiatement avant
num_list.append(n)
return pd.DataFrame(num_list,columns=["num"])
** cut_number ** inclus ici est une fonction pour obtenir le nombre immédiatement avant "personne".
def cut_number(split_tweet,index):
start_i = index #Une variable qui représente la position où le numéro a commencé dans le tweet
# "Homme"Renvoie 0 si le nombre immédiatement avant n'est pas de type str (10000 est approprié)
if not split_tweet[index] in list(map(str,range(0,10000))):
return 0
ans = split_tweet[start_i] # "Homme"Obtenez le numéro juste avant
while True:
#Ajouter à la gauche de ans tant que les nombres continuent
if split_tweet[start_i-1] in list(map(str,range(0,9))):
start_i -= 1
ans = split_tweet[start_i] + ans
#Renvoie ans lorsque le nombre est terminé
else:
return ans
Permettez-moi d'expliquer un peu pourquoi une telle fonction est nécessaire. Par exemple, s'il y a une phrase "Aujourd'hui, il y a 123 personnes infectées", si vous essayez de diviser par mecab,
tagger.parse("123 personnes sont infectées aujourd'hui").split()
# => ['aujourd'hui', 'de', 'infection', 'La personne', 'Est', '1', '2', '3', 'Homme']
De cette manière, 1, 2 et 3 ont été séparés. Dans l'état actuel des choses, seul le dernier chiffre du nombre de personnes infectées peut être obtenu, j'ai donc créé ** cut_number ** pour obtenir le nombre correct.
Une autre fonction qui apparaît dans ** auto_search ** est ** wait **, qui est une fonction qui visualise le temps restant jusqu'à la prochaine recherche automatique. (C'est comme un bonus car cela n'a rien à voir avec la fonction de l'unité principale.)
def waiting(div,wait_time,count):
clear_output()
for i in range(1,wait_time//div+1):
print("waiting: |"+"*"*i+" "*(wait_time//div-i)+"|")
print("\n--RESULT--")
print(count)
time.sleep(div)
clear_output()
print("searching on Twitter...")
En raison de la nature de l'algorithme, il n'est pas toujours possible d'attraper le rapport préliminaire du nombre de personnes infectées, donc j'essaye en fait de le déplacer et d'ajuster les paramètres. (Le code ci-dessus utilise la valeur déjà ajustée)
Voici le résultat de l'exécution de ** 7/19 **.
(Exécution avec ʻitem = 30`)
À ce moment, LINE a reçu la notification suivante.
Si vous entrez y dans le champ de saisie continuer?, La recherche se poursuivra, mais le nombre de personnes infectées annoncé à Tokyo ce jour-là est de 188, donc ça va. (Même si vous continuez à rechercher, vous ne recevrez pas de notifications répétées car pre_mode = 188.)
(Exécution avec ʻitem = 100`)
En attendant, il est affiché comme ceci. Comme vous pouvez le voir dans RESULT, il n'y a aucun candidat qui dépasse 50%, donc aucune notification ne viendra. Au contraire, après un certain laps de temps depuis l'annonce du nombre de personnes infectées, même le nombre correct diminuera.
Sur la base des résultats des tests, je vais énumérer les futurs problèmes.
rate = 0.5
, mais en fonction de l'heure de la journée, une valeur incorrecte peut être détectée comme valeur préliminaire.Je souhaite continuer à exécuter ce programme quotidiennement et à le tester pour confirmer ces problèmes.
Il semble que vous pouvez obtenir la valeur préliminaire du nombre de personnes infectées en précisant le tweet de l'agence de presse officielle sans prendre la décision majoritaire à partir de divers tweets (et c'est exact), mais je ne sais pas exactement où tweeter le plus rapidement. Il n'y a pas de telle méthode, j'ai donc essayé cette méthode. Au fait, je l'ai testé le 18/07, mais le taux de tweet de "290" a dépassé 80% immédiatement après l'annonce, probablement parce que le nombre de personnes infectées à Tokyo était de 290. En réponse à cela, 7/19 a été initialement exploité comme «taux = 0,8», mais a échoué car la notification n'est pas arrivée même si la valeur préliminaire est sortie. C'était à moi de baisser le taux et de l'ajuster. Il est difficile de parler de différents degrés selon les jours, mais j'ai hâte de voir comment des notifications précises peuvent être faites avec le simple algorithme de "ramasser de nombreux nombres murmurés". C'est pourquoi cela peut inclure la poursuite de l'intérêt en tant que développement personnel plutôt que d'utilisation pratique lol
Recommended Posts