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

TwitterBotの作成②

今回は、botに簡単な学習をさせてみた。

まだ途中だが、現時点での実装完了部分を書き留めておく。

(前回: TwitterBotの作成① - Hello World !)

bot.py

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

import twitter
import sys
from time import sleep
from collections import defaultdict
from module import remove_stopwords
import random
import igo.Tagger

# pika_shi
CONSUMER_KEY="XXXXXXXXXXXX"
CONSUMER_SECRET="XXXXXXXXXXXX"
ACCESS_TOKEN="XXXXXXXXXXXX"
ACCESS_TOKEN_SECRET="XXXXXXXXXXXX"

api = twitter.Api(consumer_key=CONSUMER_KEY,
                      consumer_secret=CONSUMER_SECRET,
                      access_token_key=ACCESS_TOKEN,
                      access_token_secret=ACCESS_TOKEN_SECRET,
                      cache=None)

# pika_shi_bot
bot_CONSUMER_KEY="XXXXXXXXXXXX"
bot_CONSUMER_SECRET="XXXXXXXXXXXX"
bot_ACCESS_TOKEN="XXXXXXXXXXXX"
bot_ACCESS_TOKEN_SECRET="XXXXXXXXXXXX"

bot_api = twitter.Api(consumer_key=bot_CONSUMER_KEY,
                      consumer_secret=bot_CONSUMER_SECRET,
                      access_token_key=bot_ACCESS_TOKEN,
                      access_token_secret=bot_ACCESS_TOKEN_SECRET,
                      cache=None)

# 初期設定
since = 0
tweet_dic = {} # {id : tweet, …}

for i in range(11):
    # TL取得
    TL = api.GetFriendsTimeline(since_id=since)
    since = TL[0].id

    for tweet in TL:
        # reply除去
        while 1:
            if tweet.text[0] == '@':
                tweet.text = tweet.text[tweet.text.find(' ')+1:len(tweet.text)]
            else:
                break

        #print tweet.user.screen_name + ' > ' + tweet.text
        tweet_dic[tweet.id] = tweet.text

    tweet_list = tweet_dic.items() # [(id,tweet)…]

    sleep(60*5)

# 形態素解析
t = igo.Tagger.Tagger('ipadic_gae', gae=True)
tf = defaultdict(list) # {word : [id,id,…]],…}
for tweet in tweet_list:
    l = t.parse(tweet[1])
    for m in l:
        #print m.surface,m.feature
        # 名詞かつ日本語かつ2文字以上のものを抽出
        if m.feature.split(',')[0] == u"名詞" and m.feature.split(',')[len(m.feature.split(','))-1] != u"*" and len(m.surface) >= 2:
            # ストップワードと、同じツイートに複数出てくる単語は除去
            if not remove_stopwords(m.surface) and tweet[0] not in tf[m.surface]:
                tf[m.surface].append(tweet[0])

# 最頻出単語を検索
max = 0 # idの個数の最大値
for key in sorted(tf.keys()):
    #print key,tf[key]
    if len(tf[key]) > max:
        max = len(tf[key])

# 最頻出単語を含むツイートのIDのリストを生成
id_list = []
for key in sorted(tf.keys()):
    if len(tf[key]) == max:
        id_list.extend(tf[key])

# その中からランダムで1つを選択し、つぶやく
id = random.choice(id_list)
for tweet in tweet_list:
    if tweet[0] == id:
        bot_api.PostUpdate(tweet[1])

module.py

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

# ストップワードの除去
def remove_stopwords(word):
    seq = []

    f = open('Japanese.txt','r')
    while 1:
        s = f.readline().rstrip()
        if not s:
            break
        seq.append(unicode(s,'utf-8'))
    f.close()

    stopwords = frozenset(seq)
    #print type(stopwords)
    return word in stopwords

・学習法・アルゴリズム

1.
@pika_shi(Twitter)のTLを約1時間分取得し、reply除去した後に格納する。

2.
取得したツイートを形態素解析し、名詞かつ日本語かつ2文字以上かつストップワードでない単語を抽出。

また、ストップワードは除去し、1ツイートに同じ単語が複数回出てくる場合は、1回とカウントする。

3.
2で抽出された名詞の中で、最も出現回数が多かったもの(最頻出単語)を検索する。

4.
最頻出単語を含むツイートの中で、ランダムに1つを選択し、つぶやく。


簡単な例をあげる。

以下の様なTLがあったとする。

Aさん:地震だ。
Bさん:めっちゃ揺れたー
Cさん:おなかすいた
Dさん:今の地震?
Eさん:眠い

2を満たし、最も出現回数が多い単語は「地震」である。
したがってbot

地震だ。
今の地震?

のいずれか1つをランダムでツイートする。

・注意点

MeCabは重くてGAEに乗らない

形態素解析MeCabを用いてプログラムを作成していたが、いざGAEにあげる時に、重くてGAEに乗らないことが判明。

そこで、igo-python(igo-python 0.9.3 : Python Package Index)を導入。
MeCabと同じ形式で出力してくれるので、大幅にプログラムを変更することなく済んだ。

ちなみに、

ImportError: No module named igo.Tagger

がなかなか消えず苦労した。igoディレクトリをルートディレクトリに直接置くことで解消された。

フォルダはこんな感じになってる。

・今後の課題

・ツイート内に@を含むものは取得しないようにする。

・@pika_shi(Twitter)のTLでは限界があるので、学習用のTLを作成し、様々なTLを取得したい。


次はreplyを実装しよう。