Ceci explique comment collecter des données Twitter avec python et comment détecter les rafales pour les données textuelles de séries chronologiques.
Techniquement, il est similaire aux articles précédents suivants.
Articles précédents: J'ai recueilli des tweets sur "Princess Kuppa" avec python et j'ai essayé de détecter les rafales https://qiita.com/pocket_kyoto/items/de4b512b8212e53bbba3
Afin de confirmer la polyvalence de la méthode adoptée à cette époque, à partir du 10 mars 2020, nous nous sommes entraînés à collecter des données Twitter et à détecter des rafales de mots qui coexistent avec «corona» avec le sujet «corona» comme mot-clé. J'ai essayé de.
La méthode de collecte est essentiellement la même que celle des articles précédents.
Tout d'abord, préparez-vous à la collecte de tweets, comme le chargement de la bibliothèque.
#Informations clés de connexion pour la collecte de données Twitter
KEYS = { #Listez la clé que vous avez avec votre compte
'consumer_key':'*********************',
'consumer_secret':'*********************',
'access_token':'*********************',
'access_secret':'*********************',
}
#Collecte de données Twitter (préparation à la collecte)
import json
from requests_oauthlib import OAuth1Session
twitter = OAuth1Session(KEYS['consumer_key'],KEYS['consumer_secret'],KEYS['access_token'],KEYS['access_secret'])
Pour savoir comment obtenir une clé de connexion pour collecter des données Twitter, le site Reference [1] est facile à comprendre.
La fonction de collecte de tweets est définie comme suit. Étant donné que l'emplacement du tweet n'est pas utilisé cette fois, l'argument par défaut (Aucun) peut être défini. De plus, comme vous ne pouvez rechercher que 100 tweets à la fois, vous devez faire des requêtes répétées avec une instruction for, mais il était plus intelligent de le gérer en dehors de la fonction d'acquisition de données Twitter, alors je l'ai implémenté de cette façon. Cette zone suit la méthode d'écriture de Reference [2].
#Fonction d'acquisition de données Twitter
def getTwitterData(key_word, latitude=None, longitude=None, radius=None, mid=-1):
url = "https://api.twitter.com/1.1/search/tweets.json"
params ={'q': key_word, 'count':'100', 'result_type':'recent'} #Paramètres d'acquisition
if latitude is not None: #Jugement uniquement par latitude
params = {'geocode':'%s,%s,%skm' % (latitude, longitude, radius)}
params['max_id'] = mid #Recevez uniquement des tweets avec des identifiants plus anciens
req = twitter.get(url, params = params)
if req.status_code == 200: #Quand une communication normale est possible
tweets = json.loads(req.text)['statuses'] #Obtenir des informations sur le tweet de la réponse
#Ingéniosité pour prendre le tweet le plus ancien (* Il semble y avoir une meilleure façon d'écrire)
user_ids = []
for tweet in tweets:
user_ids.append(int(tweet['id']))
if len(user_ids) > 0:
min_user_id = min(user_ids)
else:
min_user_id = -1
#Méta-information
limit = req.headers['x-rate-limit-remaining'] if 'x-rate-limit-remaining' in req.headers else 0
reset = req.headers['x-rate-limit-reset'] if 'x-rate-limit-reset' in req.headers else 0
return {'tweets':tweets, 'min_user_id':min_user_id, 'limit':limit, 'reset':reset}
else: #Lorsque la communication normale n'est pas possible
print("Failed: %d" % req.status_code)
return {}
J'ai créé une fonction de contrôle (getTwitterDataRepeat) pour exécuter les fonctions ci-dessus en continu. Pour éviter d'être pris dans la limite de demandes, il attendra automatiquement lorsque vous êtes sur le point d'être pris dans la limite.
#Acquisition continue des données Twitter
import datetime, time
def getTwitterDataRepeat(key_word, latitude=None, longitude=None, radius=None, mid=-1, repeat=10):
tweets = []
for i in range(repeat):
res = getTwitterData(key_word, latitude, longitude, radius, mid)
if 'tweets' not in res: #Quitter si une erreur survient
break
else:
sub_tweets = res['tweets']
for tweet in sub_tweets:
tweets.append(tweet)
if int(res['limit']) == 0: #Faites une pause si vous atteignez la limite
#Calcul du temps d'attente.Reprise après la limite + 5 secondes
now_unix_time = time.mktime(datetime.datetime.now().timetuple()) #Obtenir l'heure actuelle
diff_sec = int(res['reset']) - now_unix_time
print ("sleep %d sec." % (diff_sec+5))
if diff_sec > 0:
time.sleep(diff_sec + 5)
mid = res['min_user_id'] - 1
print("Nombre de tweets acquis:%s" % len(tweets))
return tweets
En mettant en œuvre de cette manière, il est possible de collecter automatiquement des tweets sans se soucier de la limite supérieure des requêtes. Après cela, je voulais collecter les tweets séparément par fuseau horaire, j'ai donc exécuté le script suivant.
#référence[3]J'ai emprunté la fonction qui a été créée dans
import time, calendar
def YmdHMS(created_at):
time_utc = time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y')
unix_time = calendar.timegm(time_utc)
time_local = time.localtime(unix_time) # 2018/9/Fixé à 24
return time.strftime("%Y/%m/%d %H:%M:%S", time_local)
#Recevez des tweets sur Corona toutes les 6 heures pendant une semaine
tweet_corona = {}
mid = -1
for t in range(4*7):
tweets = getTwitterDataRepeat("couronne", mid=mid, repeat=10)
old_tweet = tweets[-1] #Le tweet le plus ancien que j'ai collecté
key = YmdHMS(old_tweet["created_at"]) #Fonction YmdHMS
tweet_corona[key] = tweets #Gardez le temps du tweet le plus ancien comme clé
mid = old_tweet["id"] - 15099494400000*6 #Récupérez environ 6 heures en arrière
Je voulais collecter les tweets rétroactivement d'ici 6 heures, donc je soustrais 15 099 494 400 000 * 6 du plus ancien tweet. Cette valeur de 15 099 494 400 000 est déterminée par les spécifications d'ID tweet de Tweeter. L'ID de tweet de Twitter a une structure dans laquelle l'horodatage en millisecondes + le numéro de la machine émettant l'ID + le numéro de séquence est poussé sur 64 bits. (Référence [4])
Jusqu'à présent, nous avons pu collecter les tweets contenant "Corona" par ordre chronologique. Tout d'abord, afin de comprendre les données, je voudrais visualiser la fréquence d'apparition des mots dans l'ordre chronologique.
J'ai défini la fonction suivante, l'ai analysée morphologiquement avec janome et compté la fréquence d'apparition des mots.
#Analyse morphologique des phrases et conversion en sac de mots
from janome.tokenizer import Tokenizer
import collections
import re
def CountWord(tweets):
tweet_list = [tweet["text"] for tweet in tweets]
all_tweet = "\n".join(tweet_list)
t = Tokenizer()
#Transformé à la forme originale, seulement la nomenclature, supprimer un caractère, limité à la consommation continue de kanji, kana plat, katakana
c = collections.Counter(token.base_form for token in t.tokenize(all_tweet)
if token.part_of_speech.startswith('nom') and len(token.base_form) > 1
and token.base_form.isalpha() and not re.match('^[a-zA-Z]+$', token.base_form))
freq_dict = {}
mc = c.most_common()
for elem in mc:
freq_dict[elem[0]] = elem[1]
return freq_dict
WordCloud a été utilisé comme méthode de visualisation. Je l'ai implémenté comme suit.
#Visualisation avec Word Cloud, fonction de visualisation Word Cloud
def color_func(word, font_size, position, orientation, random_state, font_path):
return 'white'
from wordcloud import WordCloud
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
from matplotlib.font_manager import FontProperties
fp = FontProperties(fname=r'C:\WINDOWS\Fonts\meiryo.ttc', size=50) #Support japonais
def DrawWordCloud(word_freq_dict, fig_title):
#Modifier les paramètres par défaut et modifier la palette de couleurs"rainbow"changer en
wordcloud = WordCloud(background_color='white', min_font_size=15, font_path='C:\WINDOWS\Fonts\meiryo.ttc',
max_font_size=200, width=1000, height=500, prefer_horizontal=1.0, relative_scaling=0.0, colormap="rainbow")
wordcloud.generate_from_frequencies(word_freq_dict)
plt.figure(figsize=[20,20])
plt.title(fig_title, fontproperties=fp)
plt.imshow(wordcloud,interpolation='bilinear')
plt.axis("off")
Avec ces, Visualisez la fréquence des occurrences de mots dans l'ordre chronologique.
production: (Omis) : : (Omis) : : (Omis) : : (Omis) : : (Omis) :
L'influence de mots qui coexistent facilement avec le mot «corona» comme «nouveau modèle», «virus» et «infection» est ressortie fortement. A partir de ce résultat de visualisation, il est difficile de comprendre le mot qui est devenu un sujet brûlant en raison de l'influence de "corona", nous allons donc essayer de le détecter automatiquement.
En utilisant l'ensemble de données collectées cette fois et une méthode appelée détection de rafale, je voudrais détecter automatiquement le mot qui est devenu un sujet brûlant en raison de l'influence de "corona". Concernant la méthode de détection des rafales, dans le livre, "Machine learning of web data (machine learning professional series) = UTF8 & btkr = 1) ”, mais il y a peu d'articles de commentaires sur le net. Cette fois, article de commentaire du laboratoire Inui Suzuki de l'Université Tohoku, qui est célèbre comme un laboratoire lié au traitement du langage naturel. 2FTrend% 20Analysis), je voudrais essayer d'implémenter et d'appliquer la méthode de détection de rafale.
Cette fois, j'ai essayé de détecter les rafales en utilisant un index appelé Moving Average Convergence Divergence (MACD). En tant que méthode de détection des rafales, la méthode annoncée par Kleinberg en 2002 semble être souvent utilisée comme base de référence, mais la MACD annoncée par He et Parker en 2010 semble être plus simple et moins coûteuse en calcul.
↓ Quant à l'explication de MACD, je voudrais la citer telle quelle car elle est facile à comprendre depuis le laboratoire Inui-Suzuki.
[Explication de MACD]
MACD à un certain moment est
MACD = (Moyenne de l'indice de mouvement de la période f passée de la valeur de la série temporelle) - (Moyenne de l'indice de mouvement de la période s passée de la valeur de la série temporelle) Signal = (Moyenne de l'indice de mouvement de la valeur MACD au cours de la dernière période t) Histgram = MACD - Signal
Ici, f, s et t sont des paramètres (f <s), et ils sont collectivement écrits sous la forme MACD (f, s, t). Dans cette expérience, MACD (4, 8, 5), qui a également été utilisé dans l'expérience de He et Parker (2010), a été adoptée. Lorsque MACD est utilisé comme indice technique, on dit que Histgram montre la force de la tendance en augmentant le statut de "Signal <MACD" comme tendance et en abaissant le statut de "MACD <Signal" comme tendance. Cette fois, la période de 15 minutes est considérée comme un groupe (15 minutes), et la fréquence d'apparition des mots apparaissant sur Twitter pendant cette période divisée par 15, c'est-à-dire que le taux d'apparition [fois / minute] est utilisé comme valeur observée. Nous avons effectué une analyse des tendances par MACD. La valeur de la moyenne de l'indice mobile requise pour le calcul MACD peut être calculée séquentiellement, et cette analyse de tendance peut être mise en œuvre comme un algorithme de streaming, nous pensons donc qu'elle convient à l'analyse de tendance à partir de Big Data.
D'après l'explication ci-dessus, MACD a été implémenté comme suit.
# Moving Average Convergence Divergence (MACD)Calculs de
class MACDData():
def __init__(self,f,s,t):
self.f = f
self.s = s
self.t = t
def calc_macd(self, freq_list):
n = len(freq_list)
self.macd_list = []
self.signal_list = []
self.histgram_list = []
for i in range(n):
if i < self.f:
self.macd_list.append(0)
self.signal_list.append(0)
self.histgram_list.append(0)
else :
macd = sum(freq_list[i-self.f+1:i+1])/len(freq_list[i-self.f+1:i+1]) - sum(freq_list[max(0,i-self.s):i+1])/len(freq_list[max(0,i-self.s):i+1])
self.macd_list.append(macd)
signal = sum(self.macd_list[max(0,i-self.t+1):i+1])/len(self.macd_list[max(0,i-self.t+1):i+1])
self.signal_list.append(signal)
histgram = macd - signal
self.histgram_list.append(histgram)
En utilisant ce programme, du mercredi 4 mars 2020 au mardi 10 mars 2020 En raison de l'influence de Corona, je voudrais détecter automatiquement le mot qui est devenu un sujet brûlant.
#Détection en rafale des mots classés parmi les 100 premiers mots des tweets dans chaque fuseau horaire
top_100_words = []
i = 0
for freq_dict in datetime_freq_dicts:
for k,v in freq_dict.items():
top_100_words.append(k)
i += 1
if i >= 100:
i = 0
break
top_100_words = list(set(top_100_words)) #Limité à des mots uniques
print(len(top_100_words))
#Acquisition du résultat du calcul MACD
word_list_dict = {}
for freq_dict in datetime_freq_dicts:
for word in top_100_words:
if word not in word_list_dict:
word_list_dict[word] = []
if word in freq_dict:
word_list_dict[word].append(freq_dict[word])
else:
word_list_dict[word].append(0)
#Normalisation
word_av_list_dict = {}
for k, v in word_list_dict.items():
word_av_list = [elem/sum(v) for elem in v]
word_av_list_dict[k] = word_av_list
#Calcul(He and Parker(2010)Mêmes paramètres que)
f = 4
s = 8
t = 5
word_macd_dict = {}
for k, v in word_av_list_dict.items():
word_macd_data = MACDData(f,s,t)
word_macd_data.calc_macd(v)
word_macd_dict[k] = word_macd_data
#Détection de rafale
word_burst_dict = {}
for k,v in word_macd_dict.items():
burst = max(v.histgram_list) #Puisque Histgram montre la force de la tendance, prenez la valeur maximale dans la période
word_burst_dict[k] = burst
Le résultat de la saisie des données est le suivant.
i = 1
for k, v in sorted(word_burst_dict.items(), key=lambda x: -x[1]):
print(str(i) + "Rang:" + str(k))
i += 1
production: 1ère place: Kuro 2ème place: Lotte Marines 3e place: Terrain 4e place: bureau du quartier 5ème place: Dignité 6ème place: bord 7ème place: Auto-apprentissage 8ème place: Livreur 9e place: le méthanol 10e place: Kohoku 11ème place: sérum 12ème place: Eplus 13e place: harcèlement 14e place: Équipement 15e place: Snack 16e place: Sagawa Kyubin 17e place: Libero 18e place: Miyuki 19e place: Déesse 20e place: Psyché 21e place: en direct 22e place: Université de la ville de Yokohama 23e place: Dépression 24e place: volume entier 25e place: Korohara 26e place: épidémie de bête 27e place: remboursement 28e place: Apparition 29e place: Obligation 30ème place: Display : (Omis) :
«Tsuba», «Kuro», «Lotte Marines», etc. ont été détectés comme des mots qui sont devenus un sujet brûlant en raison de l'influence de «Corona». Les résultats pour les autres mots étaient généralement convaincants.
Ensuite, j'ai également essayé d'estimer le moment où c'était devenu un sujet brûlant.
<détails> Les résultats de la visualisation sont les suivants. Le match sans assistance Yakult Swallows vs Lotte Marines a eu lieu
Nous sommes le samedi 7 mars, il semble donc que nous puissions estimer correctement.
Depuis le 10 mars (mardi), «méthanol» semble être l'un des mots les plus chauds. Les résultats de la saisie des données du 3/11 (mercredi) au 3/18 (mercredi) sont les suivants. production:
1ère place: Termes
2ème place: Saya
3e place: Majestic Legon
4e place: difficile
5ème place: Civil
6e place: les gens de la Terre
7e place: Juan
8e place: Ville
9e place: le cannabis
10e place: Paraiso
11e place: Conférence de combat
12ème place: Ranbu
13e place: Laura Ashley
14ème place: Musical
15e place: impossible
16e place: Estimation
17e place: Honey
18e place: Chasing
19e place: Citron
20e place: Performance
21e place: Reçu
22e place: Épée
23ème place: Enquête
24e place: Macron
25e place: financement du cloud
26e place: Okeya
27e place: Grand-mère
28e place: Sourire
29e place: Montant total
30e place: Possédé
:
(Omis)
: Etc. ont été détectés comme des tweets qui sont devenus un sujet brûlant momentanément. Le moment où il est devenu un sujet brûlant est le suivant. Cette fois, j'ai essayé de détecter les sursauts avec le thème "Corona".
Techniquement, il s'agit d'une réimpression du contenu de l'article précédent, mais je pense qu'un résultat d'analyse raisonnable a été obtenu.
Dans l'article précédent, le thème était "Princesse Kuppa", mais nous avons pu confirmer que la méthode elle-même est très polyvalente. Je souhaite continuer à relever le défi de l'analyse des données Twitter. [1]
[2019] Méthode spécifique pour s'inscrire à l'API Twitter et obtenir un jeton de clé d'accès
https://miyastyle.net/twitter-api
[2]
Obtenez une grande quantité de données Twitter de Starba avec python et essayez l'analyse de données Partie 1
https://qiita.com/kenmatsu4/items/23768cbe32fe381d54a2
[3]
Comment gérer les tweets acquis par l'API Streaming
http://blog.unfindable.net/archives/4302
[4]
Numérotation évolutive et flocon de neige
https://kyrt.in/2014/06/08/snowflake_c.html
[5]
Projet 311 du laboratoire Inui Suzuki de l'Université Tohoku / Analyse des tendances
http://www.cl.ecei.tohoku.ac.jp/index.php?Project%20311%2FTrend%20Analysis
[6]
Dan He and D. Stott Parker(2010)
「Topic Dynamics: An Alternative Model of 'Bursts' in Streams of Topics」
https://dollar.biz.uiowa.edu/~street/HeParker10.pdf#Visualisation des résultats
import numpy as np
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
from matplotlib.font_manager import FontProperties
fp = FontProperties(fname=r'C:\WINDOWS\Fonts\meiryo.ttc', size=10) #Support japonais
x = np.array(sorted(tweet_corona.keys()))
y1 = np.array(word_macd_dict["Lotte Marines"].histgram_list)
y2 = np.array(word_macd_dict["Auto-apprentissage"].histgram_list)
y3 = np.array(word_macd_dict["Livreur"].histgram_list)
y4 = np.array(word_macd_dict["méthanol"].histgram_list)
y5 = np.array(word_macd_dict["goûter"].histgram_list)
y6 = np.array(word_macd_dict["harcèlement"].histgram_list)
plt.plot(x, y1, marker="o")
plt.plot(x, y2, marker="+", markersize=10, markeredgewidth=2)
plt.plot(x, y3, marker="s", linewidth=1)
plt.plot(x, y4, marker="o")
plt.plot(x, y5, marker="+", markersize=10, markeredgewidth=2)
plt.plot(x, y6, marker="s", linewidth=1)
plt.xticks(rotation=90)
plt.title("Résultat de la détection de rafale", fontproperties=fp)
plt.xlabel("Date et l'heure", fontproperties=fp)
plt.ylabel("Résultat de la détection de rafale", fontproperties=fp)
plt.ylim([0,0.2])
plt.legend(["«Lotte Marines»",""Auto-apprentissage"", ""Livreur"",""méthanol"", ""goûter"",""harcèlement""], loc="best", prop=fp)
(Post-scriptum 3/18) Résultats du 3/11 (mercredi) au 3/18 (mercredi)
i = 1
for k, v in sorted(word_burst_dict.items(), key=lambda x: -x[1]):
print(str(i) + "Rang:" + str(k))
i += 1
Résumé et avenir
référence