[PYTHON] Extraire des mots populaires soudains avec l'API de streaming Twitter

L'API de streaming ne prend pas en charge le filtrage japonais, elle ne peut capter qu'environ 1% des tweets, et je pense que beaucoup de gens pensent que ce n'est pas facile à utiliser. Je me suis demandé s'il y avait une utilité pour une telle API de streaming, alors j'y ai pensé, alors je l'ai fait.

Préparation

Tout ce dont vous avez besoin, ce sont les données de nombre de mots (stockées dans sqlite) toutes les 10 minutes obtenues à partir de l'API de streaming de Twitter. Les champs DB sont ymd, hour, minute, word_dict, tweet_cnt. Année, mois, jour ('2014-06-01'), heure ('22'), minute ('10' (par incréments de 10 minutes de 00 à 50)), ensemble de mots de type dictionnaire mariné, toutes les 10 minutes, respectivement. Le nombre de tweets. J'ai pensé après l'avoir fait, mais j'ai fait une erreur en concevant la DB. Il ne servait à rien de séparer la date, l'heure et les minutes. .. Je pense que je l'ai fait stupide, oui. Pour plus d'informations sur l'utilisation de l'API Twitter, reportez-vous à la page décrite dans Diviser les données Twitter en SPAM et HAM.

Ce que j'ai fait

Code de référence

python


# coding: utf-8

import sqlite3 as sqlite
from collections import defaultdict
import cPickle as pickle
import copy
import matplotlib.pyplot as plt
import re, unicodedata
from normalizewords import Replace # !!!!!À!!!Ou capitalisation, pleine largeur
from math import floor, sqrt

stopword = ('Veuillez décrire en fonction de l'objectif tel que des pictogrammes',)

class DataCreater:
    date = []
    tweet_cnt = []
    ex_words_store = []
    now_words_store = []
    new_break_words = set()
    bin_cnt = 0
    p = re.compile("[!-/:-@[-`{-~]")
    
    def __init__(self, dbname, word_limit, ofname, oftcntname,ofnewword,ofcos):
        self.con = sqlite.connect(dbname)
        self.word_limit = word_limit
        self.ofword = open(ofname, 'w',1000)
        self.oftcnt = open(oftcntname, 'w',1000)
        self.ofnewwords = open(ofnewword,'w',1000)
        self.ofcos = open(ofcos,'w',1000)
    
    def __def__(self):
        self.ofword.close()
        self.oftcnt.close()
        self.ofnewwords.close()
        self.ofcos.close()

    def re_aggregate(self,span,con_bin=10):
        response = self.get_data_yeald()
        itr, tweet_cnt, word_cnt = self.initiarize_cnt()
        s_date = None
        while 1:
            res = response.fetchone()
            if res is None: break

            #print res[0]+', '+res[1]+', '+res[2]+', '+str(res[4])
            tweet_cnt += int(res[4])
            word_cnt = self.aggregate_word_cnt(pickle.loads(str(res[3])), word_cnt) 
            
            if itr==0:
                s_date = res[0]+' '+res[1].zfill(2)+':'+res[2]
                
            if itr == span-1:
                date = res[0]+' '+res[1].zfill(2)+':'+res[2]
                sorted_word_list = self.sort_word_dict(word_cnt)
                self.output_topN_word(s_date, sorted_word_list)
                self.output_tweet_cnt(s_date, tweet_cnt)
                self.date.append(s_date)
                self.tweet_cnt.append(tweet_cnt)
                s_date = date                
                    
                self.bin_cnt += 1
                self.store_now_dict(sorted_word_list[:self.word_limit])
                print len(self.now_words_store)
                if self.bin_cnt >= con_bin:
                    if len(self.ex_words_store)!=0:
                        self.store_new_words(sorted_word_list[:self.word_limit])
                        cos_sim = self.calculate_cos_similarity(sorted_word_list[:self.word_limit])
                        self.output_new_words(s_date)
                        self.output_cos_sim(s_date,cos_sim)
                        self.ex_words_store = copy.deepcopy( self.now_words_store )
                        self.now_words_store.pop(0)
                        self.new_break_words = set()
                    else:
                        self.ex_words_store = copy.deepcopy( self.now_words_store )
                        self.now_words_store.pop(0)
                    
                itr, tweet_cnt, word_cnt = self.initiarize_cnt()
            else:
                itr += 1
                
    def get_data_yeald(self, start_date=None, end_date=None):        
        return self.con.execute("select ymd, hour, minute, word_dict,tweet_cnt from word_count")            
                
    def initiarize_cnt(self):
        return 0, 0, defaultdict(int)

    def aggregate_word_cnt(self, new_word_dic, orig_word_dic):
        for k,v in new_word_dic.items():
            if k not in stopword:
                m = self.p.search(unicodedata.normalize('NFKC', unicode(k)))
                if m is None:
                    orig_word_dic[k] += v
        return orig_word_dic
    
    def sort_word_dict(self, word_dict):
        lst = word_dict.items()
        lst.sort(lambda p0,p1: cmp(p1[1],p0[1])) # get Top N data
        return lst
            
    def calculate_cos_similarity(self, sorted_wordlist):
        ex_words =[]
        now_word_list = []
        for w_list in self.ex_words_store:
            ex_words +=w_list  
        for k,_ in sorted_wordlist:
            now_word_list.append(k)
        numerator = sum([1 for c in now_word_list if c in ex_words])
        denominator =  sqrt(len(ex_words) * len(now_word_list))
        return 1-float(numerator) / denominator if denominator != 0 else 1        
            
    def output_topN_word(self, date, sorted_word_list):
        if len(sorted_word_list) >=self.word_limit:
            s_list = [ st[0]+':'+str(st[1]) for st in sorted_word_list[:self.word_limit]]
            s = '\t'.join(s_list)
            self.ofword.write(date+'\t'+s+'\n')
        else:
            s_list = [ st[0]+':'+str(st[1]) for st in sorted_word_list[:self.word_limit]]
            s = '\t'.join(s_list)
            self.ofword.write(date+'\t'+s+'\n')

    def output_tweet_cnt(self, date, cnt):
        s = date+'\t'+str(cnt)
        self.oftcnt.write(s+'\n')

    def output_new_words(self,date):
        s = '\t'.join(list(self.new_break_words))
        print date, s
        self.ofnewwords.write(date+'\t'+s+'\n')
        
    def output_cos_sim(self, date, cos_sim):
        self.ofcos.write(date+'\t'+str(cos_sim)+'\n')
        
    def store_now_dict(self, sorted_wordlist):
        words = [k for k,_ in sorted_wordlist]
        self.now_words_store.append(words)
    
    def store_new_words(self, sorted_wordlist):
        ex_words =[]
        for w_list in self.ex_words_store:
            ex_words +=w_list  
        for k,_ in sorted_wordlist:
            if k not in ex_words:
                self.new_break_words.add(k)

if __name__=='__main__':
    dbname = 'stream_word_cnt.db'
    ofname = 'topN_words'
    oftcnt = 'tweet_count'
    ofnewword = 'new_word'
    ofcos = 'cos_simularity'
    word_top = 100 #haut Combien de mots obtenir
    span = 6 #Combien de comptes en unités de 10 minutes devraient être combinés et recomptés
    
    dc = DataCreater(dbname, word_top, ofname, oftcnt,ofnewword,ofcos)
    dc.re_aggregate(span,con_bin=24) #con_bin est le nombre de portées pour comparer la similarité
    
    tick = int(floor(len(dc.tweet_cnt)/7))
    
    plt.plot(range(len(dc.tweet_cnt)), dc.tweet_cnt)
    plt.xticks(range(0, len(dc.tweet_cnt), tick), dc.date[::tick], rotation=40)
    plt.show()

Résultat expérimental

J'avais des données que j'avais sauvegardées du 10 au 25 juin, alors j'ai essayé. En conséquence, les mots liés à la Coupe du monde ont été pris vers 5 heures du matin, les mots liés au tremblement de terre du 16 ont été repris, et les mots tels que fortes pluies et tonnerre ont été extraits les jours de forte pluie. C'est très simple à faire, mais j'ai de bonnes données. La dissemblance calculée par la similitude cosinus a également beaucoup réagi à l'heure de la Coupe du monde (notamment l'heure de diffusion du match contre le Japon) et à l'heure du tremblement de terre.

Résumé

Je pensais regarder les 10 premiers mots, mais la plupart des mots de spam tweet montent en haut. Il semble qu'il puisse également être utilisé comme moyen de supprimer des mots contenus dans ce spam (un simple filtre anti-spam qui ne nécessite pas de maintenance). J'ai le sentiment que les données de l'API de streaming peuvent être utilisées de cette manière.

Désolé de vous déranger, mais si vous avez des points étranges, veuillez commenter.

Recommended Posts

Extraire des mots populaires soudains avec l'API de streaming Twitter
Utiliser l'API Twitter avec Python
Extraire les données Twitter avec CSV
Soutenez-vous avec l'API Twitter
Update_with_media réussi avec l'API Twitter
Choisissez uniquement du japonais croustillant avec l'API de streaming Twitter
Collecter des informations sur Twitter avec Python (API Twitter)
Reconnaissance vocale en streaming avec l'API Google Cloud Speech
Publier à partir d'un autre compte avec l'API Twitter
Suivi automatique à l'aide de l'API de streaming avec Tweepy
Tweetez régulièrement avec l'API Twitter Go language
Accédez à l'API Twitter après l'authentification Oauth avec Django
[Life hack] Bot de support Anna pour femmes avec API Twitter
Exploration avec Python et Twitter API 1 - Fonction de recherche simple
YOLP: extraire la latitude et la longitude avec l'API Yahoo! Geocoder.
Twitter OAuth avec Django
Extruder avec l'API Fusion360
Extraire EXIF avec des gorgées
Essayez d'utiliser l'API Twitter rapidement et facilement avec Python
J'ai essayé la gestion du suivi avec l'API Twitter et Python (facile)
Créez un robot de réponse automatique en temps réel à l'aide de l'API Twitter Streaming
Rationalisez la collecte d'informations avec l'API Twitter et les robots Slack