メカアンジュ(https://twitter.com/MECHA_ANGE)について
技術的な補足ブログを書く。

デッデッデデデデ!(カーン!)


なお、Pythonは3x系を使用する。


■アンジュ氏の過去ツイートの取得について
Twitterは仕様上、1週間以上前のツイートを遡れないので
動画ではGithubに転がっている「GetOldTweets-python」を使用した。

なお、動画では「Exporter.py」の66行目を以下に書き換えている。

書き換え前
outputFile.write(('\n%s;%s;%d;%d;"%s";%s;%s;%s;"%s";%s' % (t.username, t.date.strftime("%Y-%m-%d %H:%M"), t.retweets, t.favorites, t.text, t.geo, t.mentions, t.hashtags, t.id, t.permalink)))

書き換え後
outputFile.write(('\n%s' % (t.text)))

IDやファボ数など不要なデータを出力ファイルに
書き込まないようにしているだけなので
自分でCSVファイルを整形するよ、という方は特に必要ない。

あとはGithubの説明書通りに実行すれば
簡単に対象アカウントの過去ツイートを根こそぎ掘れるハズ。



■実際ツイートする部分
取得したツイートをまず形態素解析で分解する。
今回はJanomeを使っているのでPIPを叩いてインストール。
インストールしたら適当にインポートしておく。


from janome.tokenizer import Tokenizer


先程出力したCSVファイルをテキストファイルにした後に読み込む。
Windowsだと十中八九エンコード周りでToLOVEるので
ちゃんとUTF-8と指定しておくと優しい。

def ange_read():  
    filename = "出力したアンジュ氏のツイート.txt"
    with open(filename, "r", encoding = 'utf8') as f:
        text = f.read()
        return(text)


ツイートを形態素解析させる。
この辺がJanomeは本当に楽。

def parse(text):
    t = Tokenizer() 
    tokens = t.tokenize(text) 
    result = [ ] 
    for token in tokens:
        result.append(token.surface)
    return(result)


次に分解したものをリストに格納しておく。

def markov_dic(wordlist):
    markov = {}
    p1 = ''
    p2 = ''
    p3 = ''

    for word in wordlist:
        if p1 and p2 and p3:
            if (p1, p2, p3) not in markov:
                markov[(p1, p2, p3)] = []
            markov[(p1, p2, p3)].append(word)
        p1, p2, p3 = p2, p3, word
    return markov


分解した単語からマルコフ連鎖で文章を作る。

def generate(markov):
    global sentence
    p1, p2, p3  = random.choice(list(markov.keys()))
    count = 0
    while count < 40:
        if ((p1, p2, p3) in markov) == True:
            tmp = random.choice(markov[(p1, p2, p3)])
            sentence += tmp
        p1, p2, p3 = p2, p3, tmp
        count += 1


ただ、これではノイズが酷いので少し整形する。
CSVファイルの変換時にノイズ除去したなら特に必要ない。

  
    # 最初に出てくる句点(。)までを取り除く
    sentence = re.sub('^.+?。', '', sentence)
    # 最後の句点(。)から先を取り除く
    if re.search('.+。', sentence):
        sentence = re.search('.+。', sentence).group()
    # URL除去
    if re.search('.+http', sentence):
        sentence = re.search('.+http', sentence).group()
    # ハッシュタグ除去
    if re.search('.+#', sentence):
        sentence = re.search('.+#', sentence).group()
    # 特定ワード削除
    sentence = re.sub('」', '', sentence)
    sentence = re.sub('「', '', sentence)
    sentence = re.sub('youtu.be', '', sentence)
    sentence = re.sub('pic', '', sentence)
    sentence = re.sub('【', '', sentence)
    sentence = re.sub('】', '', sentence)
    sentence = re.sub(':', '', sentence)
    sentence = re.sub('@ YouTubeさんから', '', sentence)


なんか他に良い整形案がある気もする。

最後に文章が重複していた場合に備えてそれらを取り除く。
どうでもいいけど、
ちょうふく か じゅうふく かで毎回悩む。

def overlap():
    global sentence
    sentence = sentence.split('。')
    if '' in sentence:
        sentence.remove('')
    new = []
    for str in sentence:
        str = str + '。'
        if str=='。':
            break
        new.append(str)
    new = set(new)
    sentence=''.join(new)



■ツイートする
TwitterAPI周りは定評のあるTweepyを使用するので
これも良きところでインポートしておく。


import tweepy


そして難関、コンシューマキーとアクセストークン。
アプリ開発をTwitterに申請取ってきて貼り付ける。

#取得したキーとトークン
CONSUMER_KEY = 'ほげほげ'
CONSUMER_SECRET = 'ほげほげ'
ACCESS_TOKEN = 'ほげほげ'
ACCESS_SECRET = 'ほげほげ'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

#APIインスタンスを作成
api = tweepy.API(auth,timeout=180)


最後に上記をまとめて実行する。


#分解する
text=ange_read()
wordlist = parse(text)
markov=markov_dic(wordlist)

#組み立てる
while(not sentence):
  generate(markov)
  overlap()
api.update_status(status=sentence)


これで出来た……気がする。



■新しい語彙を学習させる
しかし、今のままでは過去のツイートライブラリから
文章を組み立てることしか出来ない。
新しいツイートを積極的に辞書に取り入れるように少し改良する。

def kousin():
olddic=[]
with open('text.txt', 'r',newline='',encoding='utf-8') as g:
line = g.readline()
while line:
olddic.append([line.replace('\n','').replace('\'','&sing')
.replace('\"','&quot').replace(',','&cam')])
line = g.readline()
old_id=olddic[0]
olddic.pop(0)
tweet_data = olddic
count=0
for tweet in tweepy.Cursor(api.user_timeline,screen_name = "Ange_Katrina_",exclude_replies = True,include_rts= False).items():
if count==0:
new_id=tweet.id
if int(tweet.id)>int("".join(old_id)):
tweet_data.append([tweet.text.replace('\n','')
.replace('\'','&sing').replace('\"','&quot').replace(',','&cam')])
count+=1
with open('text.txt', 'w',newline='',encoding='utf-8') as f:
writer = csv.writer(f, lineterminator='\n')
writer.writerow([new_id])
writer.writerows(tweet_data)


これを呼び出せば、実行毎にアンジュ氏の
新しいツイートを探してきて辞書に追加してくれる。





以上、簡単ながら今回の成果物。
不明な点はコメントくださいまし。



bc5ed888


参考文献:
学習するTwitterbotの作り方
浜崎あゆみ形態素解析botの作成から始動まで