指定アカウントのツイートをWordCloudで可視化する方法


「Twitterデータを使って、何か面白いことができないか」の第三弾です。

第一回:
「停電」に関するツイートをpythonで収集して、WordCloudで可視化してみた
https://qiita.com/pocket_kyoto/items/0f43c9fdce87bddd31cf
第二回:
「クッパ姫」に関するツイートをpythonで収集して、バースト検出してみた
https://qiita.com/pocket_kyoto/items/de4b512b8212e53bbba3

今回は、シンプルに、指定アカウントのツイートを取得して、
WordCloudで可視化してみました。

Twitterデータって、どうやったら収集できるの?

以下の流れで収集できます。

  1. 開発者用のTwitterアカウントを登録する
  2. Twitter APIに利用者登録する
  3. API利用のためのアクセスキー・トークンを取得
  4. Twitter REST APIsで、データを収集

詳しくは、第一回記事を御覧ください。

指定アカウントのツイートを収集する

まずは、ライブラリの読み込みなど、ツイート収集の準備です。
Twitter REST APIsの出力は、json形式であるため、jsonライブラリを使います。
また、pythonからREST APIsを簡単に呼び出せるように、requests_oauthlibライブラリを使います。

# Twitterデータ収集用のログインキーの情報
KEYS = { # 自分のアカウントで入手したキーを記載
        'consumer_key':'*********************',
        'consumer_secret':'*********************',
        'access_token':'*********************',
        'access_secret':'*********************',
       }

# Twitterデータの収集(収集準備)
import json
from requests_oauthlib import OAuth1Session
twitter = OAuth1Session(KEYS['consumer_key'],KEYS['consumer_secret'],KEYS['access_token'],KEYS['access_secret'])

指定アカウントのツイート収集用の関数は、以下のように書きました。
user_name(@以降のアカウント名)を引数としています。
1回あたり最大100ツイートしか検索できないため、for文で複数回リクエストできるようにしています。

# Twitterデータ取得関数
def getAccountTwitterData(user_name, repeat=10):

    url = "https://api.twitter.com/1.1/statuses/user_timeline.json"
    params ={'screen_name':user_name,'exclude_replies':True,'include_rts':False,'count':200} #取得パラメータ
    tweets = []

    mid = -1

    for i in range(repeat):
        if mid != -1: # 初回のみmax_idの指定を解除する
            params['max_id'] = mid # midよりも古いIDのツイートのみを取得する
        res = twitter.get(url, params = params)
        if res.status_code == 200: #正常通信出来た場合

            sub_tweets = json.loads(res.text) #レスポンスからツイート情報を取得

            user_ids = []
            for tweet in sub_tweets:
                user_ids.append(int(tweet['id']))
                tweets.append(tweet)

            # ループで取得したmidよりも古いツイートを取るための工夫(※もっと良い書き方ありそう)
            if len(user_ids) > 0:
                min_user_id = min(user_ids)
                mid = min_user_id - 1
            else:
                mid = -1
            print(mid) # 時系列で見た時に最も古いツイートID

        else: #正常通信出来なかった場合
            print("Failed: %d" % res.status_code)
            break

    print("ツイート取得数:%s" % len(tweets))
    return tweets

この関数を用いて、特定ユーザーのツイートを収集してみます。
総フォロワー数ランキング1位の有吉弘行さんのアカウント("ariyoshihiroiki")のツイートを収集してみます。

tweets = getAccountTwitterData("ariyoshihiroiki", repeat=30)

出力:
1083030050134323201
1052193588430364671
1022730204936953855
996980908119900161
965901986422927360
927507559023460352
901354707137871872
883995701314584575
850964015756869631
823160757894291455
796014648101175296
781414278850936831
763211195511771135
747450926097563647
728578679194820607
708969135716196351
706835898747367423
-1
:
(中略)
:
-1
ツイート取得数:2520


2520のツイートを収集できました。
一定量のツイートは収集できましたが、Twitter APIから、特定ユーザーの全ツイートにアクセスすることは仕様上できないようです。

取得したツイートを可視化する

以下のような関数を定義して、janomeで形態素解析して、単語の出現頻度をカウントした後、WordCloudで可視化しました。

# 文章を形態素解析して、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()

    # 原形に変形、名詞のみ、1文字を除去、漢字・平仮名・カタカナの連続飲みに限定
    c = collections.Counter(token.base_form for token in t.tokenize(all_tweet) 
                            if token.part_of_speech.startswith('名詞') 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で可視化する関数

# Word Cloudで可視化、WordCloud可視化関数
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) #日本語対応

def DrawWordCloud(word_freq_dict, fig_title):

    # デフォルト設定を変更して、colormapを"rainbow"に変更
    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")

有吉弘行さんのアカウントに含まれるツイートを可視化してみます。

freq_dict = CountWord(tweets)
DrawWordCloud(freq_dict, "%sさんのつぶやきキーワード" % "ariyoshihiroiki")

出力:


できました。
ラジオという単語や、田中さん、上島さんなどの仲の良いメンバーの名前が目立ちます。

ちなみに孫正義さんのアカウント("masason")のツイートを可視化すると以下のようになります。

tweets = getAccountTwitterData("masason", repeat=30)
freq_dict = CountWord(tweets)
DrawWordCloud(freq_dict, "%sさんのつぶやきキーワード" % "masason")

出力:
329646069589884927
241826873217257472

(中略)

-1
ツイート取得数:3068


原発関連のツイートが目立つことが分かります。

まとめと今後

高度な分析に取り組もうとすると、やはりREST APIs で収集できる範囲では不足な気がしますが、
ユーザーアカウント毎のツイートを簡易に取得できることが分かったので、応用できそうな予感はします。

Twitterデータの他の活用方法についても探っていこうと思います。