隣のデスク覗く言語さん

unityとかc#とかの勉強・発見ログです.参考まで.

【解説】仮想通貨の『何が』Twitter上で盛り上がっているのかをトピックモデル分析①

はじめに

前回行ったtwitterでの仮想通貨に関するツイートに対するLDA分析の手順の解説です.
思いの外アクセスが多かったので,もう少し具体的に公開していこうと思います.
 
前回は
です.ご参照あれ.
 
今後,だいたいこんな手順で公開していく予定.
 
1.Pythonによるデータ収集
2.LDAの前処理-ノイズ除去と形態素解析-
3.Perplexityの算出による評価
4.本格的なlda分析
5.総評価・まとめ
 
まずは,1.Pythonによるデータ収集 です.
 

内容

諸々まとめ

言語:Python 2.7
ライブラリ:tweepy 他
検索ワード:「仮想通貨 OR ビットコイン OR bitcoin OR BTC OR アルトコイン
期間:1月31日0時0分0秒〜2月6日23時59分59秒の間約一週間分
ただし,RTとbotは検索対象から除く.
 

ソースコード

早速ソースコード掲載
(TwitterAPIのためのトークンは予め取得しているものとします)
 
collecter_only_txt.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import tweepy
import urllib2
import csv
import datetime
import re
import codecs
import time
import sys
import gc
#いらないimportもあるかもしれない
 
print('start...')
#分析時間の計測開始
start = time.time()
 
#トークンまとめ
CONSUMER_KEY        = ''
CONSUMER_SECRET     = ''
ACCESS_TOKEN_KEY    = ''
ACCESS_TOKEN_SECRET = ‘'
 
#apiを取得
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)
 
#ツイート取得エラーの回数を数える
error_count=0
 
#api.searchのcountを利用する
#180で15分が目安というか限界
get_data=180
 
def set_twitter_api():
    try:
        auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
        auth.set_access_token(ACCESS_TOKEN_KEY, ACCESS_TOKEN_SECRET)
        api = tweepy.API(auth)
    except Exception as e:
        print "[-] Error: ", e
        api = None
 
#宣言,getdataの回数分だけデータを取得する
def search_tweet(api,max_id,count,tweet_data):
    
    #繰り返し回数の出力
    if(count%10==1):
        time_check(api)
        print(count)
    
    #ウェイト.5秒×180が理想
    #time.sleep(4)
    print("wait...")
    print(max_id)
    #time_check(api)
    
    #データ取得部
    #最初の一回目は最新から,二回目以降最新から撮ったtweetIDの末尾から取得
    if(max_id==0):
        result = api.search(q='アルトコイン OR 仮想通貨 OR BTC OR ビットコイン OR bitcoin\
        -bot -rt'\
        ,count=100,show_user=True, lang="ja",wait_on_rate_limit = True)
    else:
        #取得エラー回避(100回エラーが出たら強制終了,それまで再帰
        try:
            result = api.search(q='アルトコイン OR 仮想通貨 OR BTC OR ビットコイン OR bitcoin\
            -bot -rt'\
            ,count=100,show_user=True, lang="ja",wait_on_rate_limit = True,max_id=max_id)
        except Exception as e:
            print "[-] Error: ", e
            global error_count
            error_count += 1
            print(error_count)
            if(error_count>100):
                sys.exit()
            #一応待機してから再帰
            time.sleep(10)
            search_tweet(api,max_id,count,tweet_data)
            
    
    #tweetIDの末尾を記録
    max_id = result[-1].id
    max_id = max_id-1
    #print(result.max_id)
 
    #データ記録部
    for tweet in result:
        tmp=tweet.text.replace('\n','')
        tmp_t=tmp.encode('utf_8')
        #JSTに合わせるための補正(+9時間)
        tmp_c=tweet.created_at + datetime.timedelta(hours=9)
        tmp_i=tweet.id
        tmp_d=tweet.source.encode('utf_8')
        tmp_u=tweet.user.name.encode('utf_8')
        #print(tweet.source)
        #wirteの時点でタブ区切り指定できるので採用
        tweet_data.append([tmp_i,tmp_c,tmp_t,tmp_u,tmp_d,tweet.retweet_count,tweet.favorite_count])
    
    #繰り返し回数足し算
    count=count+1
    
    #get_data分取得が終わったら終了
    if(count<get_data):
        writecsv(tweet_data,max_id)
        #メモリ軽減のためのリセット
        del tweet_data
        gc.collect()
        tweet_data =
        set_twitter_api()
        search_tweet(api,max_id,count,tweet_data)
    else:
        writecsv(tweet_data,max_id)
        print(tmp_c)
        print("Last check max_id:{0}".format(max_id))
 
#csvファイルを作成する部分(正確にはtsvファイル)
def writecsv(data,max_id):
    #初回だけ列名を作成
    if(max_id==0):
        #タブ区切り
        #with open('txt_data.csv', 'a') as f:
        with open('txt_data.tsv', 'a') as f:
                writer = csv.writer(f, lineterminator='\n',dialect=csv.excel_tab,)
                writer.writerow(["id","created_at","text","user","device","rt","fav"])
                #writer = csv.writer(f, lineterminator='\n')
                #writer.writerow(["id\tcreated_at\ttext\tuser\tdevice\trt\tfav"])
                
        pass
    else:
        #with open('txt_data.csv', 'a') as f:
        with open('txt_data.tsv', 'a') as f:
            writer = csv.writer(f, lineterminator='\n',dialect=csv.excel_tab,)
            #writer = csv.writer(f, lineterminator='\n')
            writer.writerows(data)
        pass
 
#main関数
def main():
    #初期値.続きからやりたければmax_idを指定してカウントを1以上にする
    max_id=0
    count=0
    #とりあえず空のデータ.ここにappendしていく
    tweet_data =
    
    set_twitter_api()
    print("main do")
    if(max_id==0):
        writecsv(api,max_id)
    #引数はtweepyの基本と最新tweetIDと取得回数
    search_tweet(api,max_id,count,tweet_data)
    time_check(api)
 
#時間と残り回数の出力
def time_check(api):
    #残り実行回数の取得(tweepyの限界)と実行時間の出力
    limit_data=api.rate_limit_status()
    j=(limit_data['resources']['search']['/search/tweets']['remaining'])
    print("Remain:{0}".format(j))
    elapsed_time = time.time() - start
    print ("elapsed_time:  {:.3f}".format(elapsed_time) + "[sec]")
 
#最初に実行される部分
if __name__ == '__main__':
    main()
    
 

ソースコードの解説

多分プロフェッショナルから見たら無駄が多いかもしれません…が,一応これでデータ収集できます.
def search_tweet(api,max_id,count,tweet_data):
の部分で検索ワードをベタ打ちして,検索ワードにヒットしたツイートを取得しています.
取得しているデータは,ツイートID,ツイート日時,本文,ユーザ名,ツイートされたデバイス名,リツート数,ファボ数です.
やろうと思えばもっと多くのデータを取得することもできます.
 

工夫点

.tsvファイルによる書き出し
通常こういうデータは.csvで取得しますが,このコードでは.tsvファイルで取得しています.
これは,ツイートの本文に頻繁に,(カンマ)が現れることがあるからです.これを回避するために,タブ区切りでデータを取得する必要がありましたので,そうしました.
max_idの指定
ツイートIDを取得しているので,もうちょっと遡ってツイートを取得したいと思ったらmax_idを指定することで可能です.これを上手いこと繰り返すことで1週間分丸々データを集めることができます.
検索ワード指定
また,当然といえば当然ですが,仮想通貨以外の検索ワードにしたら,そのワードを含むツイートを取得できるので,様々な分析を行うことができます.
 
で,これを2月6日くらいからイソイソと回し始めた結果,34万3555件ものデータを集めることができたわけです.
 

課題

・180回以上データを収集し始めるとメモリが圧迫される
→何処かで余計な処理が発生しているか,tweepyのapiが悪い影響及ぼしている?
・対処法
max_idを指定すればそこから再検索できるので,pythonの処理を止めながら進めればサクサクできる.
 
pythonは不慣れですができたほうだと自分を褒める…
 
今回は以上です.
次回はノイズ除去や形態素解析について述べていこうと思います.
 
 
参考まで.