今回はツイッターからツイートデータを取得し、それをWordCloudというライブラリを使って可視化してみたいと思います。
Word Cloud関連の記事は、既に多くあり特に目新しいものではないですが、可視化ツールとしてはなかなかインパクトがあるので、テキストマイニング関連の分析の一例として今回やってみました!
ちなみに、今回、好きな芸人の中の一人である、スピードワゴン小沢さんのツイートを取得して、可視化してみました。(勝手にごめんなさい。。。)
結果をまず先にお見せします!
今回の流れ
Word Cloudでは、頻出する単語ほど、つまり特徴的な単語ほど大きな文字で表示されます。右下の「好き」「幸せ」「友達」という言葉がまず目に入りました。小沢さんのツイートは、とても詩的で素敵です。そんな小沢さんの人柄、芸術性溢れたツイート内容がうまく可視化できているのではないかと思います!
さて、この図をどのように作るかについてですが、
- Twitterデータ取得
- 形態素解析
- Word Cloudによる可視化
の流れで説明していきます。
また、同様のことをRでも実践しました。Rをお使いの方はこちらも是非ご覧ください。
www.randpy.tokyo
Twitterデータの取得
Twitterデータは、APIを使って取得します。APIを使用するために必要なkeyは以下の4つです。- Consumer Key
- Consumer Secret
- Access Token
- Access Token Secret
これらのkeyを取得する手順については、以下記事で大変わかりやすくまとめられていますので、そちらをご参照ください。
www.randpy.tokyo
さて、keyを無事に取得することができましたら、さっそくPythonの方でAPIを叩いていきたいと思います。
PythonからTwitter APIを使用するための色々なラッパーが存在しますが、今回はそれらを使わずに'requests_oauthlib'というライブラリを使ってAPIを叩いていきたいと思います。('requests_oauthlib'はAPI認証に使います)
ラッパーを使ったほうがもちろん便利で楽チンなのですが、カスタマイズしてデータを取得したい際はやはり自分でスクリプトを書く必要があるので、ケースバイケースで使い分けて頂ければいいかと思います。
'requests_oauthlib'がまだ入っていない方はpipでインストールしてください。
pip install requests_oauthlib
以下、APIを叩くまでの基本的なスクリプトになります。
import requests from requests_oauthlib import OAuth1Session #取得したkeyを以下で定義する access_token = '' access_token_secret = '' consumer_key = '' consumer_key_secret = '' # タイムライン取得用のURL url = "https://api.twitter.com/1.1/statuses/user_timeline.json" #パラメータの定義 params = {'screen_name':'twitter垢の@以降を入力', 'exclude_replies':True, 'include_rts':False, 'count':200} #APIの認証 twitter = OAuth1Session(consumer_key, consumer_key_secret, access_token, access_token_secret) #リクエストを投げる res = twitter.get(url, params = params)
基本的にはこれだけのコードで事足ります。
URLの部分は、タイムラインのデータを取得したい、あるキーワードによる検索を行いたいなど、目的によって変わってきます。
今回はある特定のユーザーのタイムラインを取得したいので、statuses/user_timeline.jsonを使用します。
取得したいデータごとの対応するURLについては、https://developer.twitter.com/en/docs/api-reference-indexこちらの公式サイトを確認するのが一番手っ取り早いでしょう。
なお、パラメータの部分で取得するデータをカスタマイズできます。
- 'screen_name':ユーザーを指定。
- 'exclude_replies':リプライを含むかどうか
- 'include_rts':リツイートを含むかどうか
- 'count':一度に取得するツイート件数の指定。デフォルト20、maxで200。
このあたりのパラメータについて詳しく知りたい方は、以下公式ドキュメントを参考にしてください。
https://developer.twitter.com/en/docs/tweets/timelines/overview
実際にツイート取得と諸々の処理
以下が実際にツイート文をとってくるスクリプトの部分になります。
f_out = open('/path/filename','w') for j in range(100): res = twitter.get(url, params = params) if res.status_code == 200: # API残り limit = res.headers['x-rate-limit-remaining'] print ("API remain: " + limit) if limit == 1: sleep(60*15) n = 0 timeline = json.loads(res.text) # 各ツイートの本文を表示 for i in range(len(timeline)): if i != len(timeline)-1: f_out.write(timeline[i]['text'] + '\n') else: f_out.write(timeline[i]['text'] + '\n') #一番最後のツイートIDをパラメータmax_idに追加 params['max_id'] = timeline[i]['id']-1 f_out.close()
注意点として、二点挙げます。
まず、一つ目にAPIのリクエスト制限があるので、limit = res.headers['x-rate-limit-remaining']で残りのリクエスト回数を取得して、制限に達したら、15分間停止するようにしてます。(15分間で、制限がリセットされる仕様)
もう一点は、ツイートをどんどん遡っていく必要がありますが、一度に取得できるツイート数はmaxで200個なので、取得できた分の中で一番古いツイートのIDを取得して、次にリクエストをかけるときには、一番古いツイートIDの次に古いIDから取得するようにしています。(スクリプト最後の部分)
200ツイート取得するという処理を100回繰り返しているので、合計20000ツイート取得できているはずですが…何故か2000ツイートまでしか取得できませんでした。
リツイートとリプライは除外するようにパラメータ設定しているのですが、どうやらTwitter APIではそれらを一旦取得してその後除外するようにしているっぽいです。
なのでリツイートとリプライが多いと、たくさん取得しているのに結果は少ない…。ということになるようです。
もし解釈が間違っている場合は、コメントいただけると助かります。
訂正と追記
すいません、完全に間違っていました。
GET statuses/user_timelineを見ると、元々各ユーザーの最新ツイートは、リツイートも含めて3,200までしか取得できないようです。
更にそこからリツイートを除外すると、大体2000件ぐらいになるということですね。
はースッキリ!
形態素解析 & Word Cloud
テキストを取得できたら、今度はそれぞれ単語に分解する必要があります。よく使われるツールとしてはMeCabというものがありますが、インストールするのが結構大変だったりします。
そこで今回は、手っ取り早く分析したいという方にお勧めのjanomeというライブラリを使って形態素解析していきます。
janomeは内部で辞書を持っているので、Mecabをインストールしてなくても動きます。
こちらはpipでインストールできるので、入れてない方はインストールしてみてください。
ちなみに、wordcloudもまだ入れてない方はついでにインストールしちゃいましょう。
pip install janome pip install wordcloud
wordcloudは依存ライブラリがいくつかあるので、エラーが出た方は必要なライブラリをインストールしてください。
ちなみにanacondaを使っている方は、必要なライブラリが既に揃っているはずなので、おそらくエラーが起きないはずです。
Word cloudを実践
以下wordcloudを使うまでのデータ加工スクリプトです。#coding:utf-8 import csv from janome.tokenizer import Tokenizer import matplotlib.pyplot as plt from wordcloud import WordCloud from bs4 import BeautifulSoup from collections import Counter, defaultdict #名詞だけ抽出、単語をカウント def counter(texts): t = Tokenizer() words_count = defaultdict(int) words = [] for text in texts: tokens = t.tokenize(text) for token in tokens: #品詞から名詞だけ抽出 pos = token.part_of_speech.split(',')[0] if pos == '名詞': words_count[token.base_form] += 1 words.append(token.base_form) return words_count, words with open('./file_name','r') as f: reader = csv.reader(f, delimiter='\t') texts = [] for row in reader: text = row[0].split('http') texts.append(text[0]) words_count, words = counter(texts) text = ' '.join(words) #word cloud fpath = "~/Library/Fonts/ヒラギノ丸ゴ ProN W4.ttc" wordcloud = WordCloud(background_color="white", font_path=fpath, width=900, height=500).generate(text) plt.figure(figsize=(15,12)) plt.imshow(wordcloud) plt.axis("off") plt.show()
簡単にコードの解説をします。
まず、counter()関数で名詞だけ抽出し、単語のカウントと単語のリストを作成しています。
そしてword cloudには、各単語をスペース区切りにして一つのテキストにまとめものをINPUTとして与えます。
一つ注意点としては、macで動かす場合は、fontを指定しないと文字が表示されませんので、Library/Fonts/~で日本語の文字フォーマットを選択してください。
スクリプトが無事に動きますと、冒頭でも見せた以下の図ができるはずです!!
小沢さんを特徴付ける単語がちゃんと強調されていますね!本当はストップワードなり設定して、ノイズを除去した上で可視化すると、もっと綺麗な図になるかと思います。
背景画像であったり、フォントや色など色々設定できるので、ぜひ色々試してみてください。
ちなみに、名詞だけでなく形容詞も含めた図がこちらになります。
そこまで大きく変わりませんでしたが、”楽しい”という言葉がとても印象的ですね。
終わりに
今回はテキストマイニング分析の一例として、Twitterデータをwordcloudで可視化してみました。結構簡単にデータも取れて分析できるので、ぜひ色々なデータて試してみてくださいー。
また、Rでも同様のWord Cloudを使った可視化をやってみました!
Rユーザーの方は是非ご覧ください。
www.randpy.tokyo
Pythonクローリング&スクレイピング -データ収集・解析のための実践開発ガイド-
- 作者: 加藤耕太
- 出版社/メーカー: 技術評論社
- 発売日: 2016/12/16
- メディア: 大型本
- この商品を含むブログ (3件) を見る