はるすえすしーのぶろぐ

ブログのないようがないよう

PythonでTwitterのマルコフ連鎖bot(多重人格)を作った話[3/3]

前回までのあらすじ

仲間だと思っていた戦士が真の魔王"Twitter API"であったことが判明した勇者たち。辛くも彼を倒した勇者たちの前に立ちはだかるのは、死ぬ間際に真の魔王が召喚した魔神であった。
世界の平和はもうすぐで訪れるだろう…

前の前:マルコフ連鎖をやってみる→https://halss.hatenablog.com/entry/hals_ai1
前:ツイート収集&ツイート→https://halss.hatenablog.com/entry/hals_ai2

2.5.ある間違い

私はここで大きな間違いに気づきます。


そう、@Hals_aiではなく@Hals_SCでTwitter Developer登録をしてしまったのです。しかし登録は時間かかるしもう一度やるのは面倒くさいのでこのままいきます。さようなら、かわいそうな@Hals_ai。。。
f:id:halss:20191006213901p:plain

3.定期的にツイートをする

やること
  • GitをインストールしてGitHubと連携する
  • プログラムとかのファイルをレポジトリに上げる(?)
  • GitHubのレポジトリとHerokuを連携し、定期的に実行されるようにする
  • 完成!

※GitとかGitHubとかの知識が非常に薄いので操作の名称だったり詳しい内容だったりが違ったりすることがあります、優しく教えてくださると幸いです

GitとかGitHubってなに

私もよくわかってません。

Git(ギット)とは、プログラムソースなどの変更履歴を管理する分散型のバージョン管理システムのことです。Gitの最大の特徴は、分散型の名の通り、ローカル環境(自分のパソコンなど)に、全ての変更履歴を含む完全なリポジトリの複製が作成されることです。
「そもそもGitって何?」、「GitとGitHubは何が違うの?」にシンプルに答えるよ-Six Apart ブログ|オウンドメディア運営者のための実践的情報とコミュニティ

今あるファイルをコピーしておいて、あとから自由に戻したりくっつけたりできる…みたいなシステムだと思っておけばいいと思います。
もとはLinux用なんですが、Windowsで動作できるようにしたGit for Windowsがあります。これを今回使います。

次にGitHubの説明です。

GitHub(ギットハブ)は、このGitの仕組みを利用して、世界中の人々が自分の作品(プログラムコードやデザインデータなど)を保存、公開することができるようにしたウェブサービスの名称です。
「そもそもGitって何?」、「GitとGitHubは何が違うの?」にシンプルに答えるよ-Six Apart ブログ|オウンドメディア運営者のための実践的情報とコミュニティ

Gitと連携させることで自分のPC等のファイルを世界に公開できます。このファイルを上げたレポジトリを後述のHerokuと連携させて使います。
分からなければググってください。ただし深追いしすぎると大変なことになります。

Gitのインストール

GitHubを開き、New repositoryから新しいレポジトリを作成しましょう。名前は"○○_ai"とかでいいです。
そのあと、Gitのインストール、GitHubとの連携をします。今後の操作は基本、このインストールしたGit Bashでやります。あと、今まで作業していたフォルダをC:\homeに入れておくと便利だと思います。
(参考1:いまさらGit for Windowsのインストール、GitHubに接続してみた。 - Qiita)
(参考2:ローカル作業フォルダをGIT管理下においてGitHubにPUSHするまで - Qiita)

ローカルからレポジトリへ

(正直お好みですが)".gitignore"ファイルを作ります。中身はこんな感じです。

chain.db
data.txt
__pycache__

次にGit Bashで以下のように入力します。

$ cd 作業しているフォルダ名
$ git init
$ git add .
$ git commit
$ git push origin master

1行目で移動、2行目でGit管理下に、3行目でインデックスにフォルダ全部を追加、4行目でそれらをローカルレポジトリに追加、5行目でGitHubのサーバーに追加します。これでローカルで変更した内容がGitHubに反映されます。4行目で突如文書編集モードに入りますが、Iキーで編集開始、escキーで編集終了、":wq"で保存です。最初見た時どうやってやめるのかわからなくて詰みました。なんて罪な設計なんだ。詰みだけに。

Heroku appの作成

heroku 初級編 - GitHub から deploy してみよう - - Qiitaを参考にHeroku appを作成してGitHubのレポジトリと連携します。「手動deployを実行しよう!」は別にしなくていいです。あとは

$ heroku git:remote -a herokuのアプリ名
set git remote heroku to https://git.heroku.com/herokuのアプリ名.git
$ git remote -v
heroku  https://git.heroku.com/herokuのアプリ名.git (fetch)
heroku  https://git.heroku.com/herokuのアプリ名.git (push)
origin  git@github.com:GitHubユーザ名/GitHubのレポジトリ名.git (fetch)
origin  git@github.com:GitHubユーザ名/GitHubのレポジトリ名.git (push)

と表示されたらGitとHerokuの連携はOKです。

$ git push heroku master

と打つだけでローカルレポジトリがHerokuのサーバーに追加され(要するに変更され)ます。

定期的に処理を実行するプログラムを作る

(参考:APSchedulerの使い方(初心者向け) - プログラミング原人の進化論)
APSchedulerというライブラリで定期的に処理を実行するようにします。

$ pip install apscheduler

でインストールし、以下のようなclock.pyを作成します。

# -*- coding: utf-8 -*-
from apscheduler.schedulers.blocking import BlockingScheduler
import os
import TextTweet
import GetTweet

# APIの秘密鍵
CK,CKS,AT,ATS=os.environ["CONSUMER_KEY"], os.environ["CONSUMER_SECRET"], os.environ["ACCESS_TOKEN_KEY"], os.environ["ACCESS_TOKEN_SECRET"]

twische = BlockingScheduler()

# 30分に一度ツイート
@twische.scheduled_job('interval',minutes=30)
def timed_job():
    TextTweet.puttweet()

# 半日に一度ツイートを取得、チェーンを作ってdbに保存
@twische.scheduled_job('interval',hours=12)
def timed_job():
    #ツイートを取得
    GetTweet.gettweet(Ck,CKS,AT,ATS)

    #data.txtに保存
    f = open("data.txt",encoding="utf-8")
    text = f.read()
    f.close()

    #チェーンを作成、dbに保存
    chain = PrepareChain(text)
    triplet_freqs = chain.make_triplet_freqs()
    chain.save(triplet_freqs, True)

if __name__ == "__main__":
    twische.start()

これで30分に一度ツイート、12時間に一度ツイート取得&チェーン作成ができるようになります。API秘密鍵のところは後述します。

Herokuでの環境構築

(参考:twitter定期botをHerokuにデプロイ - Qiita)
用意するものは、
・さっき作ったclock.py
Pythonのバージョン名を書いたruntime.txt

python-3.7.1

・何を実行するかを書いたProcfile

web : python index.py
clock : python clock.py

・実際には動かさないダミーファイルのindex.py

#-*- coding:utf-8 -*-
import os
from bottle import route, run

@route("/")
def hello_world():
        return "hello world!"

run(host="0.0.0.0", port=int(os.environ.get("PORT",5000)))

・用意するライブラリを書いたrequirements.txt(基本必要なものだけを書く、エラーの原因になる)

APScheduler==3.6.1
bottle==0.12.13
mecab-python3==0.996.2
oauthlib==3.1.0
requests==2.22.0
requests-oauthlib==1.2.0
tweepy==3.8.0
(など、以下省略)

ただし、前に使ったmacab-python-windowsはHerokuでは動かないので(おそらく環境がLinuxであるため)、mecab-python3に変更する必要があります。

環境変数を設定する

前回、API秘密鍵はとても大切という話をしました。

大切なので人に見られたらその人を消すしかないですすぐさまRegenerateしましょう。

そんな大事なことをプログラムに書いておくなんて、パスワードを紙に書いて冷蔵庫に貼っておくようなものです。そんなアホなことはできません。なので環境変数に設定しておき、プログラムからは環境変数を呼び出すだけにしておきます。プログラムの変更についてはGitHubのプログラムを実際に見てもらった方が早いと思います。

$ heroku config:set CONSUMER_KEY="xxxxxxxxxxx"
$ heroku config:set CONSUMER_SECRET="xxxxxxxxxxxxx"
$ heroku config:set ACCESS_TOKEN_KEY="xxxxxxxxxxxxxxxx"
$ heroku config:set ACCESS_TOKEN_SECRET="xxxxxxxxxxxxxxxxx"

これで設定完了です。エラーが起きるなら多分Herokuとの連携ができてません。

動かす!

あとはもう動かすだけです。
(参考:heroku runでETIMEDOUTなときの対処法と原因 - Qiita)

$ git add .
$ git commit
$ git push origin master
$ git push heroku master

これでHerokuのアプリ画面からf:id:halss:20191006233123p:plainこんな風にDeployedされていることを確認して、以下のように入力します。

$ heroku run:detached python clock.py
Running python clock.py on halsai... done, run.○○○○ (Free)
Run heroku logs --app アプリ名 --dyno run.○○○○ to view the output.

こんな風に表示されたら指示通りコピペして実行してみます。

$ heroku logs --app アプリ名 --dyno run.○○○○
2019-10-01T04:04:04.033538+00:00 heroku[run.○○○○]: Starting process with command `python clock.py`
2019-10-01T04:04:04.647220+00:00 heroku[run.○○○○]: State changed from starting to up

30分後にツイートされていれば完成です!

しかしプログラム内にバグがあると30分に一度実行しては同じところでエラーを吐き続けることになります。けなげなHerokuくん…
f:id:halss:20191006234337p:plain

ちなみに最初に生成された文章はこれです。運が悪い。

止めたいときは

$ heroku ps:stop run.○○○○

で止まります。

おわりに

Twitter botを作った話でした。正直Git~Herokuが一番時間かかった気がします。もう少し優しいといいんですけどね。
作ろう作ろうと思っていたらなぜか同時期にTwitterのFFも作っていたのでそっちもよろしければ。
qiita.com

「やっぱり@hals_aiで呟かせたい!」ってなったらTwitter Developer申請して変更しますが今のところは多重人格でいいですかね…
ご覧いただきありがとうございました!
GitHub
github.com

参考