読者です 読者をやめる 読者になる 読者になる

COBOL技術者の憂鬱

COBOLプログラマは不在にしています

映画に関するつぶやきを解析してスコアを算出する

さて、どんどん進めてまいりましょう。
今週はこれです。


個別のつぶやきを解析して、それがポジティブな内容なのかネガティブな内容なのかを判定し、スコア算出後にデータベースに反映する処理を追加し、CRONで回す。

個別のつぶやきをどう評価していくかでずいぶん悩んだのですが、日本語解析とかの世界に入っていくともうどうしようもない感じになってしまうので、ここはとてもシンプルな方法でいくことにしました。
まずは個別のつぶやきに対して、ポジティブな形容詞を束ねた正規表現を使って検索します。次に、ネガティブな形容詞を束ねた正規表現で検索し、それぞれのマッチした語数を単純に大小比較して、つぶやきの内容を判定することにします。
前回作成したプログラムは、つぶやきを取得するところで終わっていましたが、今回はそれに対して判定処理を追加し、以下のようになりました。




【get_tweet.py】

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

from google.appengine.api import urlfetch
import re
import datetime

import movies
import htmlentity2unicode

query = movies.Movies.gql('ORDER BY update_date DESC,check_time ASC')
movie = query.get()

if movie:
  api_url = 'http://search.twitter.com/search.atom?q=' + movie.title.encode('utf-8') + '&locale=ja&since_id=' + movie.since_id.encode('utf-8')
  try:
    result = urlfetch.fetch(api_url)
  except:
    movie.check_time = datetime.datetime.today()
    movie.put()
  else:
    if result.status_code == 200:
      pattern = re.compile(r'<id>tag:search.twitter.com,2005:(.*?)</id>')
      tweet_ids = pattern.findall(result.content)
      if len(tweet_ids) > 1:
        movie.since_id = tweet_ids[1]
        pattern2 = re.compile(r'<title>(.*?)</title>')
        tweet_titles = pattern2.findall(result.content)
        movie.tweet_count = movie.tweet_count + len(tweet_titles) - 1
        for i in range(len(tweet_titles)):
          if i > 0:
            tweet = htmlentity2unicode.htmlentity2unicode(tweet_titles[i]).encode('utf-8')
            pattern_good = re.compile(r'よい|よかった|すご|おもしろ|かっこよ|わら|たのし|すばら|ヨイ|ヨカッタ|スゴ|オモシロ|カッコヨ|ワラ|タノシ|スバラ|良い|良かった|凄|面白|格好よ|笑|楽し|素晴|good|nice')
            score_good_result = pattern_good.findall(tweet)
            score_good_point = len(score_good_result)
            pattern_bad = re.compile(r'わる|しょうも|つまら|ひど|ワル|ショウモ|ツマラ|ヒド|悪|酷|bad')
            score_bad_result = pattern_bad.findall(tweet)
            score_bad_point = len(score_bad_result)
            if score_good_point > score_bad_point:
              movie.score_good = movie.score_good + 1
            elif score_good_point < score_bad_point:
              movie.score_bad = movie.score_bad + 1
            else:
              movie.score_other = movie.score_other + 1
      movie.check_time = datetime.datetime.today()
      movie.put()


私の頭の中で思いついた形容詞を、正規表現の中へ適当にちりばめてみましたが、本家のFlixupではどうやっているのかが気になるところです。あちらは英語圏なので、形容詞の使い方がもっとはっきりしているような気がしますね。


上のプログラムをしばらくcronで回してみて、データストアビューアで内容を確認してみました。



うん、よい感じなのではないでしょうか。
次回はいよいよ、このデータストアの内容をブラウザから参照できるようにします。
tweet_countに占めるgood/bad/otherの割合がパッと一目で分かるように、積み上げ棒グラフかなんかで表示させようと考えているのですが、それだとgoogle chart apiが使えそうですね。そういえば今月の日経ソフトウエアでも似たようなことをやっていたような…