Dies ist eine Erklärung zum Sammeln von Twitter-Daten mit Python und zum Erkennen von Bursts für Zeitreihentextdaten.
Technisch ähnelt es den folgenden früheren Artikeln.
Frühere Artikel: Ich habe mit Python Tweets über "Princess Kuppa" gesammelt und versucht, einen Ausbruch zu erkennen https://qiita.com/pocket_kyoto/items/de4b512b8212e53bbba3
Um die Vielseitigkeit der zu diesem Zeitpunkt angewandten Methode ab dem 10. März 2020 zu bestätigen, haben wir das Sammeln von Twitter-Daten und das Erkennen von Wortschüben, die mit "Corona" koexistieren, mit dem Thema "Corona" als Schlüsselwort geübt. Ich versuchte zu.
Die Erhebungsmethode ist im Wesentlichen dieselbe wie in den vorherigen Artikeln.
Bereiten Sie sich zunächst auf die Tweet-Sammlung vor, z. B. das Laden der Bibliothek.
#Anmeldeschlüsselinformationen zum Sammeln von Twitter-Daten
KEYS = { #Listen Sie den Schlüssel auf, den Sie mit Ihrem Konto erhalten haben
'consumer_key':'*********************',
'consumer_secret':'*********************',
'access_token':'*********************',
'access_secret':'*********************',
}
#Sammlung von Twitter-Daten (Vorbereitung zur Sammlung)
import json
from requests_oauthlib import OAuth1Session
twitter = OAuth1Session(KEYS['consumer_key'],KEYS['consumer_secret'],KEYS['access_token'],KEYS['access_secret'])
Informationen zum Abrufen eines Anmeldeschlüssels zum Sammeln von Twitter-Daten finden Sie auf der Website Referenz [1].
Die Funktion zum Sammeln von Tweets ist wie folgt definiert. Da der Tweet-Speicherort diesmal nicht verwendet wird, kann das Standardargument (Keine) festgelegt werden. Da Sie nur bis zu 100 Tweets gleichzeitig durchsuchen können, müssen Sie wiederholte Anfragen mit einer for-Anweisung stellen. Es war jedoch intelligenter, diese außerhalb der Twitter-Datenerfassungsfunktion zu verwalten. Deshalb habe ich sie auf diese Weise implementiert. Dieser Bereich folgt der Schreibmethode von Referenz [2].
#Twitter Datenerfassungsfunktion
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'} #Erfassungsparameter
if latitude is not None: #Beurteilung nur nach Breitengrad
params = {'geocode':'%s,%s,%skm' % (latitude, longitude, radius)}
params['max_id'] = mid #Erhalten Sie nur Tweets mit IDs, die älter als Mitte sind
req = twitter.get(url, params = params)
if req.status_code == 200: #Wenn normale Kommunikation möglich ist
tweets = json.loads(req.text)['statuses'] #Erhalten Sie Tweet-Informationen von der Antwort
#Einfallsreichtum für die ältesten Tweets (* Es scheint einen besseren Weg zu geben, um zu schreiben)
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
#Meta-Informationen
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: #Wenn keine normale Kommunikation möglich ist
print("Failed: %d" % req.status_code)
return {}
Ich habe eine Steuerfunktion (getTwitterDataRepeat) erstellt, um die oben genannten Funktionen kontinuierlich auszuführen. Um zu vermeiden, dass Sie im Anforderungslimit hängen bleiben, wird automatisch gewartet, wann Sie im Limit gefangen werden.
#Kontinuierliche Erfassung von Twitter-Daten
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: #Verlassen, wenn ein Fehler auftritt
break
else:
sub_tweets = res['tweets']
for tweet in sub_tweets:
tweets.append(tweet)
if int(res['limit']) == 0: #Machen Sie eine Pause, wenn Sie das Limit erreichen
#Berechnung der Wartezeit.Nach Limit + 5 Sekunden fortsetzen
now_unix_time = time.mktime(datetime.datetime.now().timetuple()) #Aktuelle Zeit abrufen
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("Anzahl der erworbenen Tweets:%s" % len(tweets))
return tweets
Durch diese Implementierung ist es möglich, Tweets automatisch zu sammeln, ohne sich um die Obergrenze der Anforderungen kümmern zu müssen. Danach wollte ich Tweets getrennt nach Zeitzone sammeln, also habe ich das folgende Skript ausgeführt.
#Referenz[3]Ich habe die Funktion ausgeliehen, die in erstellt wurde
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/Fest auf 24
return time.strftime("%Y/%m/%d %H:%M:%S", time_local)
#Erhalten Sie eine Woche lang alle 6 Stunden Tweets über Corona
tweet_corona = {}
mid = -1
for t in range(4*7):
tweets = getTwitterDataRepeat("Corona", mid=mid, repeat=10)
old_tweet = tweets[-1] #Der älteste Tweet, den ich gesammelt habe
key = YmdHMS(old_tweet["created_at"]) #YmdHMS-Funktion
tweet_corona[key] = tweets #Speichern Sie die Zeit des ältesten Tweets als Schlüssel
mid = old_tweet["id"] - 15099494400000*6 #Sammle ungefähr 6 Stunden zurück
Ich wollte Tweets rückwirkend um 6 Stunden sammeln, also subtrahiere ich 15.099.494.400.000 * 6 von der ältesten Tweet-Mitte. Dieser Wert von 15.099.494.400.000 wird durch die Tweet-ID-Spezifikationen von Tweeter bestimmt. Die Tweet-ID von Twitter hat eine Struktur, in der der Millisekunden-Zeitstempel + die Nummer des Computers, der die ID ausgibt + die Sequenznummer in 64 Bit verschoben werden. (Referenz [4])
Bis zu diesem Zeitpunkt konnten wir Tweets mit "Corona" in chronologischer Reihenfolge sammeln. Um die Daten zu verstehen, möchte ich zunächst die Häufigkeit des Auftretens von Wörtern in chronologischer Reihenfolge visualisieren.
Ich definierte die folgende Funktion, analysierte sie morphologisch mit Janome und zählte die Häufigkeit des Auftretens von Wörtern.
#Morphologische Analyse von Sätzen und Umwandlung in Bag of Words
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()
#In die ursprüngliche Form umgewandelt, nur Nomenklatur, entfernen Sie ein Zeichen, beschränkt auf kontinuierliches Trinken von Kanji, Flat Kana, Katakana
c = collections.Counter(token.base_form for token in t.tokenize(all_tweet)
if token.part_of_speech.startswith('Substantiv') 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
Als Visualisierungsmethode wurde WordCloud verwendet. Ich habe es wie folgt implementiert.
#Visualisierung mit Word Cloud, Word Cloud-Visualisierungsfunktion
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) #Japanische Unterstützung
def DrawWordCloud(word_freq_dict, fig_title):
#Ändern Sie die Standardeinstellungen und die Farbkarte"rainbow"ändern
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")
Mit diesen, Visualisieren Sie die Häufigkeit von Wortvorkommen in chronologischer Reihenfolge.
Ausgabe: (Weggelassen) : : (Weggelassen) : : (Weggelassen) : : (Weggelassen) : : (Weggelassen) :
Der Einfluss von Wörtern, die leicht mit dem Wort "Corona" koexistieren, wie "neues Modell", "Virus" und "Infektion", kam stark heraus. Aufgrund dieses Visualisierungsergebnisses ist es schwierig, das Wort zu verstehen, das aufgrund des Einflusses von "Korona" zu einem heißen Thema wurde. Daher werden wir versuchen, es automatisch zu erkennen.
Mit dem diesmal gesammelten Datensatz und einer Methode namens Burst-Erkennung möchte ich automatisch das Wort erkennen, das aufgrund des Einflusses von "Corona" zu einem heißen Thema wurde. In Bezug auf die Methode der Burst-Erkennung in dem Buch "Maschinelles Lernen von Webdaten (Professional Series für maschinelles Lernen) = UTF8 & btkr = 1) ”, aber es gibt nur wenige Kommentarartikel im Netz. Diesmal Kommentarartikel des Inui Suzuki-Labors der Tohoku-Universität, das als Labor für die Verarbeitung natürlicher Sprache bekannt ist. 2FTrend% 20Analysis) möchte ich versuchen, die Burst-Erkennungsmethode zu implementieren und anzuwenden.
Dieses Mal habe ich versucht, Bursts mithilfe eines Index namens Moving Average Convergence Divergence (MACD) zu erkennen. Als Burst-Erkennungsmethode scheint die von Kleinberg im Jahr 2002 angekündigte Methode häufig als Basis verwendet zu werden, aber die von He und Parker im Jahr 2010 angekündigte MACD scheint einfacher und weniger rechenintensiv zu sein.
↓ Die Erklärung von MACD möchte ich so zitieren, wie sie ist, da sie im Inui-Suzuki-Labor leicht zu verstehen ist.
[Erklärung von MACD]
MACD zu einem bestimmten Zeitpunkt ist
MACD = (Bewegungsindex-Durchschnitt der vergangenen f Periode des Zeitreihenwerts) - (Bewegungsindex-Durchschnitt der vergangenen s Periode des Zeitreihenwerts) Signal = (Bewegungsindex-Durchschnitt des MACD-Werts in der letzten t-Periode) Histgram = MACD - Signal
Hier sind f, s, t Parameter (f <s), und diese werden zusammen als MACD (f, s, t) geschrieben. In diesem Experiment wurde MACD (4, 8, 5) übernommen, das auch im Experiment von He und Parker (2010) verwendet wurde. Wenn MACD als technischer Index verwendet wird, wird gesagt, dass Histgram die Stärke des Trends zeigt, indem der Status von "Signal <MACD" als Trend erhöht und der Status von "MACD <Signal" als Trend gesenkt wird. Diesmal wird der Zeitraum von 15 Minuten als Gruppe (15 Minuten) genommen, und die Häufigkeit des Auftretens von Wörtern, die innerhalb dieses Zeitraums auf Twitter erscheinen, geteilt durch 15, dh die Auftrittsrate [Zeiten / Minute] wird als beobachteter Wert verwendet. Wir haben eine Trendanalyse von MACD durchgeführt. Der für die MACD-Berechnung erforderliche Wert des gleitenden Indexmittelwerts kann nacheinander berechnet werden, und diese Trendanalyse kann als Streaming-Algorithmus implementiert werden. Wir sind daher der Ansicht, dass sie für die Trendanalyse aus Big Data geeignet ist.
Aus der obigen Erklärung wurde MACD wie folgt implementiert.
# Moving Average Convergence Divergence (MACD)Berechnung von
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)
Mit diesem Programm vom Mittwoch, 4. März 2020 bis Dienstag, 10. März 2020 Aufgrund des Einflusses von Corona möchte ich das Wort, das zu einem heißen Thema wurde, automatisch erkennen.
#Burst-Erkennung von Wörtern, die in Tweets in jeder Zeitzone zu den 100 besten Wörtern gehören
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)) #Beschränkt auf eindeutige Wörter
print(len(top_100_words))
#Erfassung des MACD-Berechnungsergebnisses
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)
#Normalisierung
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
#Berechnung(He and Parker(2010)Gleiche Parameter wie)
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
#Burst-Erkennung
word_burst_dict = {}
for k,v in word_macd_dict.items():
burst = max(v.histgram_list) #Da Histgramm die Stärke des Trends zeigt, nehmen Sie den Maximalwert innerhalb des Zeitraums
word_burst_dict[k] = burst
Das Ergebnis der Dateneingabe ist wie folgt.
i = 1
for k, v in sorted(word_burst_dict.items(), key=lambda x: -x[1]):
print(str(i) + "Rang:" + str(k))
i += 1
Ausgabe:
"Tsuba", "Kuro", "Lotte Marines" usw. wurden als Wörter erkannt, die aufgrund des Einflusses von "Corona" zu einem heißen Thema wurden. Die Ergebnisse für die anderen Wörter waren im Allgemeinen überzeugend.
Als nächstes habe ich auch versucht, die Zeit zu schätzen, als es ein heißes Thema wurde.
#Visualisierung der Ergebnisse
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) #Japanische Unterstützung
x = np.array(sorted(tweet_corona.keys()))
y1 = np.array(word_macd_dict["Lotte Marines"].histgram_list)
y2 = np.array(word_macd_dict["Selbststudium"].histgram_list)
y3 = np.array(word_macd_dict["Lieferant"].histgram_list)
y4 = np.array(word_macd_dict["Methanol"].histgram_list)
y5 = np.array(word_macd_dict["Snack"].histgram_list)
y6 = np.array(word_macd_dict["Belästigung"].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("Ergebnis der Burst-Erkennung", fontproperties=fp)
plt.xlabel("Datum (und Uhrzeit", fontproperties=fp)
plt.ylabel("Ergebnis der Burst-Erkennung", fontproperties=fp)
plt.ylim([0,0.2])
plt.legend([""Lotte Marines"",""Selbststudium"", ""Lieferant"",""Methanol"", ""Snack"",""Belästigung""], loc="best", prop=fp)
Die Visualisierungsergebnisse sind wie folgt.
Yakult Swallows gegen Lotte Marines hatten ein unbeaufsichtigtes Match Es ist Samstag, der 7. März, also können wir es anscheinend richtig einschätzen. Ab dem 10. März (Dienstag) scheint "Methanol" eines der heißesten Wörter zu sein.
Die Ergebnisse der Dateneingabe von 3/11 (Mittwoch) bis 3/18 (Mittwoch) sind wie folgt.
i = 1
for k, v in sorted(word_burst_dict.items(), key=lambda x: -x[1]):
print(str(i) + "Rang:" + str(k))
i += 1
Ausgabe:
Usw. wurden als Tweets erkannt, die momentan zu einem heißen Thema wurden.
Die Zeit, als es ein heißes Thema wurde, ist wie folgt.
Dieses Mal habe ich versucht, Bursts mit dem Thema "Corona" zu erkennen. Technisch gesehen ist es ein Nachdruck des Inhalts des letzten Artikels, aber ich denke, dass ein vernünftiges Analyseergebnis erzielt wurde. Im letzten Artikel war das Thema "Prinzessin Kuppa", aber wir konnten bestätigen, dass die Methode selbst sehr vielseitig ist.
Ich möchte mich weiterhin der Herausforderung der Twitter-Datenanalyse stellen.
[1] [2019] Spezifische Methode zur Registrierung bei der Twitter-API und zum Abrufen des Zugriffsschlüssel-Tokens https://miyastyle.net/twitter-api [2] Holen Sie sich mit Python eine große Menge von Starbas Twitter-Daten und probieren Sie die Datenanalyse Teil 1 aus https://qiita.com/kenmatsu4/items/23768cbe32fe381d54a2 [3] Umgang mit Tweets, die von der Streaming-API erfasst wurden http://blog.unfindable.net/archives/4302 [4] Skalierbare Nummerierung und Schneeflocke https://kyrt.in/2014/06/08/snowflake_c.html [5] Tohoku University Inui Suzuki Laborprojekt 311 / Trendanalyse 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