TwitterBot
https://scrapbox.io/files/618203fdeebbbb001d9077ed.png
TwitterBotを作成してRaspberry Piを外部から制御する
この内容自体はスマートアクアリウムには関係無いが、まずは制御する環境(会話bot)を作る
Twitter APIを扱うライブラリは「Tweepy」を使用した
https://scrapbox.io/files/618f46009f4adb001fdee560.png
要件
Twitter経由でRaspberry Piと情報のやり取りができる
仕様
仕様1:Raspberry Piからプログラムを実行すると、特定のTwitterアカウントにメンションする
仕様2:特定のTwitterアカウントにメンションするとリプライが返ってくる
仕様3:上記の会話botを起動すると、停止させるまで動作し続ける
メンション ⇒ 「@」をつけて特定アカウントにツイートを送信する行為
リプライ ⇒ 特定のツイートに対して返信ツイートを送信する行為
準備
以下の手順でTwitterの会話bot作成の準備を行う
動作させるbotのインターフェースとなるTwitterアカウントを新規作成する
TwitterにTwitter APIの利用申請を行う
申請が承認されるのを待つ(場合によってはここで数時間~数日かかる可能性もある)
承認されたAPIの認証情報を取得する
動作させるbotのインターフェースとなるTwitterアカウントを新規作成する
普段使いのTwitterアカウントではなくbotを動作させる専用のアカウントを新規作成する
作り方は通常通りでOK(特別な操作は無し)
TwitterにTwitter APIの利用申請を行う
いわゆるTwitterに「作文」を書くやつ
かつてのTwitterは自由にAPIが利用できたが、さまざまな邪悪なことが起こり現在はTwitterにAPIの利用申請を行い、承認される必要がある
ここではそのやり方の説明は行わないので以下などを参照して利用申請する
申請が承認されるのを待つ
待つ
申請、承認のフローはその時々で変わっているようで、あしゅりー.iconの場合は申請した瞬間に即承認、というか自動承認(申請内容を機械的に審査している?)されて、すぐにAPIの利用を開始することができた
承認されたAPIの認証情報を取得する
こちらも上記のURLを参考に取得して控えておく
以下の4つの情報が必要
APIキー(コンシューマキー)
APIシークレット
アクセストークン
アクセストークンシークレット
念のため記載
上記の4つの情報は他者に知られないようにし、ソースコード公開の際は絶対に漏らさないこと
設計
流れは以下の通り
Tweepyインストール
単純なツイート投稿
特定ツイートに反応してリプライする
会話botをサービス化する
Tweepyインストール
PythonにてTwitter APIを扱えるライブラリとして「Tweepy」をインストールする
code:Terminal
$ pip install tweepy
注意:2021年9月にリリースされたVer.4.0.0にて後述のStreamListenerがStreamにマージされたことで、このページのサンプルコード(Ver.3.x.x使用)は上手く動作しなくなっため、そのまま使う場合はpip install tweepy==3.10.0で3系の最新版をインストールすると良い
StreamListener has been merged into Stream (see Breaking Changes section)
あしゅりー.iconはまだ対応していないが、Ver.4.0.0以降に対応した書き方は以下のようにするらしい
Tweepyのドキュメント
単純なツイート投稿
まずは基本的な動作確認として、プログラムを実行すれば予め準備しておいた文字列をツイートするものを作る
注意:テスト段階において、bot用に用いるTwitterアカウントは鍵垢設定やフォロワー0などの状態で行い、万が一作成したbotが暴走した場合でも他者に大量のツイートを投げたり結果的にスパム行為となるような挙動にならないように心がける
code:twitter.py
import tweepy
CONSUMER_KEY = 'xxxxxxxx'
CONSUMER_SECRET = 'xxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxx'
ACCESS_TOKEN_SECRET = 'xxxxxxxx'
auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)
api.update_status(status='こんにちワールド')
控えておいた認証情報にそれぞれ書き換え、以下を実行する
code:Terminal
$ python3 twitter.py
update_status()にて指定した文字列がbot用のアカウントからツイートされることを確認する
ちなみにTwitterでは全く同じ文言のツイートは一定期間投稿できないため、上記をもう一度実施するとツイート失敗となる
ここで、api.update_status(status='@Asyley_ とうもろコーン')とすれば@Asyley_に対してメンションを送信することができる
@Asyley_の特定のツイートに対するリプライではなく、単に「@」でアカウント指定したメンションツイート
完了 ⇒ 仕様1:Raspberry Piからプログラムを実行すると、特定のTwitterアカウントにメンションする
特定ツイートに反応してリプライする
上記はツイートしたい時だけプログラムを実行すれば良いが、会話botの場合はプログラムを停止させるまで常にツイートを監視し続け、特定ツイートがあった時はそれに対して応答用の処理を実施するように動作させる
上記などを参考に、特定の文字列のツイートが呟かれた時にそれにリプライを送信するプログラムを作成する
code:tweet_listener.py
###### 「api」の認証処理までは上記twitter.pyと同様 ######
class MyStreamListener(tweepy.StreamListener):
def on_status(self, status):
reply_text = '@' + status.user.screen_name
reply_text += ' なんやこいつ'
api.update_status(status=reply_text, in_reply_to_status_id=status.id)
def on_exception(self, exception):
# 長時間動かすと1日に数回は例外を吐くため、ここで対処できると良い
pass
while True:
try:
myStreamListener = MyStreamListener()
myStream = tweepy.Stream(auth=api.auth, listener=myStreamListener)
except KeyboardInterrupt:
sys.exit()
except:
pass
$ python3 tweet_listener.pyにて上記を実行すると会話botが起動する
botの停止は「Ctrl+C」
上記の例では@Asyley_aqua という文字列を含むツイートが新規に呟かれた際にon_status()の処理が実施される
「@Asyley_aqua」は会話bot用のアカウント名を想定
つまり、@Asyley_aqua こんにちは~wのようなメンションツイートがこの条件に該当し、on_status()が動作する
on_status()では、当該ツイートの各種情報が格納されたstatusが引数で渡されており、update_status()にてメンション元のユーザーに対して「なんやこいつ」という文字列を返信(リプライ)する
ここでの注意として、リプライ先のツイートとしてin_reply_to_status_idでツイートのIDを指定しているが、これだけではリプライツイートにはならず、reply_textは@ユーザー名 ツイート内容の文字列の形で準備する必要がある
完了 ⇒ 仕様2:特定のTwitterアカウントにメンションするとリプライが返ってくる
あとはメンションツイートの内容を解析して、メンション元やツイート文字列などに応じた処理およびリプライ処理を自由に用意すれば良い
あしゅりー.icon環境では上記会話botプログラムを長期的に動作させた場合、1日に数回程度以下のようなコネクションエラーによる例外が発生してプログラムが異常終了してしまうため、on_exception()の記述により対策したことで落ちなくなった
code:exception
('Connection broken: IncompleteRead(36 bytes read)', IncompleteRead(36 bytes read))
会話botをサービス化する
上記にて作成した会話botプログラムの実行中は端末で他のことができないため、ここなどを参考にサービス化してバックグラウンドで長期的に動作させる 例えば上記プログラムを以下のように実行している場合を想定して記載する
code:Terminal
python3 /home/asyley/tweet_listener.py
python3の場所を確認
code:Terminal
$ which python3
/usr/bin/python3
/etc/systemd/system/に以下のファイルを作成する
code:twitter_bot.service
Description=twitter_bot
WorkingDirectory=/home/asyley/
ExecStart=/usr/bin/python3 /home/asyley/listening_tweet.py
User=<ユーザー名>
WantedBy=multi-user.target
<ユーザー名>は各自置き換えること
systemdにサービスとして認識されたか確認する
code:Terminal
$ systemctl list-unit-files --type=service | grep twitter_bot
twitter_bot.service disabled
twitter_bot.serviceが出てきたら認識されている
ラズパイ起動時に自動起動するようにする
code:Terminal
$ sudo systemctl enable twitter_bot
$ systemctl list-unit-files --type=service | grep twitter_bot
twitter_bot.service enabled
enabledになっていればOK
サービスを起動する
code:Terminal
$ sudo systemctl start twitter_bot
あとはその他のサービスと同様にstop restart statusなどにより操作できる
完了 ⇒ 仕様3:上記の会話botを起動すると、停止させるまで動作し続ける
注意:ラズパイ起動時、systemdにより上記サービスを自動起動した場合、まだネットワークなどの準備ができていないことでTwitterAPIとの認証でコケて上手く動作しないなどが発生しうるため、listening_tweet.pyの最初にtime.sleep(30)などでシステムが立ち上がるまで待機する時間を設けるなど、適宜対策すると良い
テロ対策
これをそのまま本番投入すると第三者に悪用され、大量のリプライを送信させられたりするので以下を参考に対策すること
活用
システム構成図
「Twitter API」が実現できたことになる
システム構成図.icon