2014年10月17日金曜日

Twitter APIとjNLPによる評判分析




Twitter APIとjNLPで日本語からの評判分析を実装してみました。

システムの構成としては

1. Twitter APIでキーワードを含む直近100ツイートを取得
2. cabochaでツイートの本文を語句解析
3. 得られた語句をjNLPで評判分析
4. 統計値を取り出してプロット
5. 重要なツイートは全文出力

という感じです。
これを毎週cronで行うことでキーワードに対する評判を時系列データとしてプロットが出来るようにしました。

pythonでやればせいぜい100行程度で実装することが出来ます。




1. Twitter APIによるQuery

Pythonだととても簡単に実装出来ます。
Consumer Keyなどは自分のを入れてください。


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# This script is to retrive search result from twitter. 
# Basic usage is for sentiment analysis.
# This will most likely to be called from analyze.sh.
#
# Usage:
#    ./twitter.py <QUERY WORD>
#
# Return:
#    List of tweets in structure below.
#    <User Name> <User ID> <Text>

from requests_oauthlib import OAuth1Session
import json
import datetime
import sys

# Twitter Authentication

CK = ''                             # Consumer Key
CS = ''         # Consumer Secret
AT = '' # Access Token
AS = ''         # Accesss Token Secert
url = "https://api.twitter.com/1.1/search/tweets.json" # タイムライン取得用のURL

# Print Date for later use

#d = datetime.datetime.today()
#date = '%s-%s-%d' % (d.year, d.month, d.day)

word = sys.argv[1]
since = sys.argv[2]
params = {"q":word, "count": 100, "since_id": since}

twitter = OAuth1Session(CK, CS, AT, AS)
req = twitter.get(url, params = params)

tweets = []

if req.status_code == 200:
    utftext = req.text.encode('utf-8')
    timeline = json.loads(utftext)
    statuses = timeline["statuses"]
    for tweet in statuses:
        tweetid = tweet["id"]
        username = tweet["user"]["name"].replace(' ', '')
        userid = tweet["user"]["id_str"]
        text = tweet["text"].replace('\n', ' ')
        tweet = {"tweetid": tweetid, "username": username, "userid": userid, "text": text}
        tweets.append(tweet)
    for tweet in tweets:
        print tweet["tweetid"], tweet["username"].encode('utf-8'), tweet["userid"].encode('utf-8'), tweet["text"].encode('utf-8')


else:
    # エラーの場合
    print ("Error: %d" % req.status_code)

2. Cabocha

Pythonで書くことも出来ましたが、簡単にbash one-linerでかけました。

cat texts$date | cabocha -f1 | awk '/名詞/{printf("%s ", $1)} /EOS/{printf("\n")}' > words$date
awkは本当にこういうとき便利ですね。


3. jNLPによる評判分析

現状、ここはかなり適当にやっています。
というかjNLPのサンプルをそのまま使っています。
cabochaによって得た名詞をそのまますべて単語単位でsentiに投げ、その総和をツイートの評判値としています。おそらくこれは良い方法ではありません。


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import codecs
from jNlp.jSentiments import *
sys.stdin = codecs.getreader('utf-8')(sys.stdin)
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
txt = sys.stdin.readlines()
#print txt

jp_wn = 'wnjpn-all.tab' #path to Japanese Word Net
en_swn = 'senti.txt' #Path to SentiWordNet
classifier = Sentiment()
sentiwordnet, jpwordnet  = classifier.train(en_swn, jp_wn)


# Print pos & neg point for each line
for line in txt:
    positive_sum = 0.0
    negative_sum = 0.0
    nouns = line.split()
    for noun in nouns:
#        print noun
        try:
            positive_score = sentiwordnet[jpwordnet[noun]][0]
            negative_score = sentiwordnet[jpwordnet[noun]][1]
            positive_sum += positive_score
            negative_sum += negative_score
        except KeyError, e:
            pass
#            print 'Not found in Dictionary.'
    print positive_sum, negative_sum


4. Gnuplotでプロット

ここではpos値とneg値を分けてプロットしました。
書いてて思ったのはscatter plotの方が思いました。あとで実装してみます。
ただしpos値, neg値=0.0のツイートが多いのでそれは消した方がいいかもしれません。


gnuplot<<EOF
   set terminal postscript enhanced color
   set title "Sentimental Analysis Report of $dateform: Raw Data"
   set xrange [0:3]
   set yrange [0:1]
   set xtics 1
   set nokey
   set xtics ('Positive' 1, 'Negative' 2)
   plot '${df}pos' using (1):1 w point notitle
   set output "${df}$date.png"
   replot '${df}neg' using (1):1 w point notitle
EOF


まぁこんな感じで100行未満で実装出来ます。
色々なライブラリに依存するので、以上のコードをコピペしても動かないとは思いますが、参考になるかと。


まだ有意義なデータを取り出すに至っていませんがこれから色々動かしてみようと思います。

0 件のコメント:

コメントを投稿