[Python]マルコフ連鎖則で友人っぽいツイートを生成するTwitterのBotを作った

#はじめに
大学生の春休み、クローリング＆スクレイピングの勉強をやっていたのですが、練習にTwitterのBotを作ってみることにしました。
友人Bの協力を得て、ツイートを分析してBっぽいツイートをするBotを作成しました。

#開発環境
Windows10上のvirtualboxでUbuntuの仮想環境を使用
Ubuntu 18.04.4 LTS

#使用技術

- マルコフ連鎖則
- MeCab
- tweepy
- MySQL
- VPS (Virtual Private Server) 

それぞれちょっとずつ説明を書きます。

##マルコフ連鎖則
まず「どうやって生成する文章にその人らしさを出すのか」「そもそも文章の自動生成ってどうやるだろうか？」と疑問を抱いて調べたところ、マルコフ連鎖則というものを発見しました。

マルコフ連鎖則の解説はこちらの記事がとてもわかりやすいので是非ご参照ください。Pythonのコードも参考にさせていただきました。**マルコフ連鎖則すごい！**てなります。

>[Python]N階マルコフ連鎖で文章生成](https://qiita.com/k-jimon/items/f02fae75e853a9c02127)

##MeCab
取得したツイートを分析する手段としてMeCabを使います。
「取得したツイートに対してMeCabを用いて形態素解析を行い単語のリストを作成→マルコフ連鎖則に従って単語を並べる」というのが基本的な文章生成の流れになります。

MeCabについての詳しい説明はこちらをご覧ください。
>[【技術解説】形態素解析とは？MeCabインストール手順からPythonでの実行例まで](https://mieruca-ai.com/ai/morphological_analysis_mecab/)


##tweepy
ツイッターを自動操作するにはTwitterが公式に提供しているTwitterAPIを使います。
TwitterAPIを使うとアカウントをプログラムから自動操作することができるようになります。

PythonからTwitterAPIを操作するときはPythonのライブラリであるtweepyが便利ということで、この本を参考にしつつネットで調べながら使い方を勉強しました。
>[Pythonクローリング＆スクレイピング ―データ収集・解析のための実践開発ガイド―](https://www.amazon.co.jp/Python%E3%82%AF%E3%83%AD%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0-%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0-%E3%83%87%E3%83%BC%E3%82%BF%E5%8F%8E%E9%9B%86%E3%83%BB%E8%A7%A3%E6%9E%90%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E5%AE%9F%E8%B7%B5%E9%96%8B%E7%99%BA%E3%82%AC%E3%82%A4%E3%83%89-%E5%8A%A0%E8%97%A4-%E8%80%95%E5%A4%AA/dp/4774183679/ref=tmm_other_meta_binding_title_0?_encoding=UTF8&qid=&sr=)

##MySQL

どうせならデータベースの勉強もしようと、TwitterAPIで取得したデータの保存をMySQLを使って保存することにしました。試作時にはテキストファイルにデータを入れてみていましたが少し動作が遅かった印象です。

MySQLについて詳しく知りたい方は下記のリンク先を参照してみてください。イメージがつかめるかと思います。
>[https://www.atoone.co.jp/column/10114/](https://www.atoone.co.jp/column/10114/)

##VPS
Botを運営するためのサーバーが必要だということで、VPSを借りました。常時起動しているパソコンを1台使えるみたいなイメージ。

必要な環境の構築にはLinuxの知識が必要で、サーバー初心者の私にはそこそこハードな作業になりましたが、MySQLやMeCabなど必要なソフトウェアをインストールしました。

CohoHaVPSで手軽に借りることができました。
>[ConoHaVPS](https://www.conoha.jp/vps/?btn_id=footer_vps)


#Botアプリの構成
やっと本題ですが、図にするとこんな感じ。
![Bot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601868/0dfcb640-8a7c-71fd-18ca-966d6b1f2b95.png)

各スクリプトの役割は以下のようにしている
@twitter_collector.py(データ収集用スクリプト)
1. TwitterAPIをPythonライブラリであるtweepyで利用して、ツイートデータを取得
2. 取得したデータから必要な要素(本文、投稿日時など)を抜きだし、データベースへ保存
3. ストリーミングAPIを利用して新規ツイートがあれば随時データベースへ追加する

@bot.py(Bot本体)
1. データベースからツイート本文を読み出し、処理しやすい形に整形
2. テキストデータをMeCabで形態素解析し、友人Bのツイートの内容の傾向をモデル化
3. 作成したモデルにしたがって友人Bらしいツイートを生成
4. TwitterAPI(Tweepy)で生成したツイートを投稿

データを集める部分とツイートを行うBot本体をわけることで管理がしやすくなっていると思います。

#Botの自動化
サーバーにCentOS8の環境を用意し、そこにMeCab、MySQL、Pythonなど必要な各ツールをインストールし環境構築を行いました

Pythonスクリプトを実行するためのシェルスクリプトをsystemdによって自動実行することでBotを動かしています。systemdについてはこちらの記事にわかりやすく解説されています。
>[systemdによる自動起動](https://www.souichi.club/technology/systemd/)

#もっと似せるために
ただマルコフ連鎖則にしたがって文章をつくらせているだけでも結構面白いツイートを生み出してくれたので楽しかったのですが、もっと似せたいなということで現時点で下記2点を工夫しています

 - 本人のツイート間隔のパターンを時間帯ごとの分布を調べ、それに従ってツイートさせる
 - 本人のツイートの文字数の分布を調べそれに従ってツイートする文字数(の範囲)を確率的に決定する

どちらも、友人Bが実際にしたツイートからデータを取得、リスト化し、その中からランダムに値を選ぶことで実現しています。

#感想
さすがに長い文章になるほど文の意味は通らなくなってしまいますが、短いツイートなら、本当に本人がいったようなツイートをすることもあります。本人が過去につぶやいた内容からランダムにワードが選ばれているので、組み合わせによっては思わず笑ってしまうツイートも生成することができました。

B君、協力してくれてありがとう。

#おわりに

最後まで読んでいただきありがとうございます。
なにかアドバイス等ありましたらコメントいただけると嬉しいです。