[Python]Twitter Botを自作してみる

Python

Twitter APIを利用して、自動返信BotモドキをPythonで作ってみました。

Twitterでは相手を指定してツイートすることができますので、ツイートに反応して返信するようなプログラムを作成してみます。

おみくじBot

簡単なサンプルとして、「おみくじ」という単語に反応して、その結果を返信するようにしたいと思います。

Botへの入力メッセージとして、「@infomisc !おみくじ」のような内容を想定しています。
「@infomisc」がツイートを送る相手(Bot)で、「!おみくじ」のメッセージでBotが反応するようにします。Bot向けのツイートという区別をするため、ここでは「!」を冒頭に付けるルールとしています。

Twitter APIアプリの権限設定

特定のツイート対してTwitter APIで返信する場合は、アプリの権限設定にWrite権限が付与されていることを確認します。

デフォルトではRead権限のみのようでしたので設定変更しました。設定変更後はトークンなどの再生成が必要なのでご注意ください。実際にハマりました。

If a permission level is changed, any user tokens already issued to that Twitter app must be discarded and users must re-authorize the App in order for the token to inherit the updated permissions.

App permissions

設定変更はDeveloper Portalで行います。

Twitter APIアプリ画面を開いて、「App permissions」の項目を表示します。「Read Only」の状態ではツイートの返信はできませんので、「Edit」を選択して権限変更を行います。

権限変更画面に移りますので、「Read and write and Direct message」にチェックして、「Save」を選択します。

確認画面が表示されますので、「Yes」を選択します。

「App permissions」画面に戻ります。「Read Only」となっていた箇所が「Read, Write and Direct Messages」に変更されていることを確認します。この後、トークンなどの再生成を行なってください。

プログラム実行時に「tweepy.errors.Unauthorized: 401 Unauthorized」といったエラーが発生した場合は、アプリの権限設定を確認してください。

    :                                                            
  File "/home/xxxxxx/.local/lib/python3.6/site-packages/tweepy/api.py", line 2                                              57, in request
    raise Unauthorized(resp)
tweepy.errors.Unauthorized: 401 Unauthorized

サンプルプログラム

Pythonのソースコードです。短いプログラムですが、これだけでBotとして機能します。

import random
import re
import tweepy

API_KEY = '**********'
API_SECRET = '**********'
ACCESS_TOKEN = '**********'
ACCESS_TOKEN_SECRET = '**********'

auth = tweepy.OAuthHandler(API_KEY, API_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)

class MyStream(tweepy.Stream):
    def on_status(self, status):
        message = status.text
        print(message)
        oper = ''
        try:
            oper = message.split()[1]
        except e:
            pass
        if oper != '' and re.match(r'!|!', oper):
            reply = ''
            if re.search(r'おみくじ', oper):
                reply = '『%s』でーーす! by infobot' % random.choice(['大吉', '吉', '中吉', '小吉', '末吉'])
            else:
                reply = 'すいません。よくわかりません。 by infobot'
            api.update_status('@%s %s' % (status.user.screen_name, reply), in_reply_to_status_id = status.id)

me = api.get_user(screen_name='infomisc')
flist = []
flist.append(me.id_str)

myStreamObj = MyStream(API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
myStreamObj.filter(follow=flist)

bot.pyとして保存して実行した結果がこちらです。

$ python bot.py
@infomisc !おみくじ
@xxx94625941 『大吉』でーーす! by infobot

※Ctrl-Cでプログラムを停止します

実際のツイート画面はこんな感じに。

他の単語にも反応するように拡張することで、優秀なBotに育てていくこともできそうですね。

以下で簡単にコードの説明をしていきたいと思います。

Twitter API準備

API_KEY = '**********'
API_SECRET = '**********'
ACCESS_TOKEN = '**********'
ACCESS_TOKEN_SECRET = '**********'

auth = tweepy.OAuthHandler(API_KEY, API_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth)

Twitter APIを利用するための事前準備部分です。APIキーやアクセストークンは適宜置き換えてください。

自動返信処理(MyStreamクラス)

class MyStream(tweepy.Stream):
    def on_status(self, status):
        message = status.text
        print(message)
        oper = ''
        try:
            oper = message.split()[1]
        except e:
            pass
        if oper != '' and re.match(r'!|!', oper):
            reply = ''
            if re.search(r'おみくじ', oper):
                reply = '『%s』でーーす! by infobot' % random.choice(['大吉', '吉', '中吉', '小吉', '末吉'])
            else:
                reply = 'すいません。よくわかりません。by infobot'
            api.update_status('@%s %s' % (status.user.screen_name, reply), in_reply_to_status_id = status.id)

ツイートを受け取った時の処理部分を担うクラスです。条件に合致したツイートを受け取るとon_status関数が呼び出されます。

受け取ったツイート情報はstatusに格納されています。status.textでツイート内容を取り出した上でmessageに格納し、split関数で内容をリスト化しています。

「@infomisc !おみくじ」というツイートの場合、

  • message.split()[0] →ツイートの宛先(ここでは@infomisc)
  • message.split()[1] → ユーザが入力したツイート内容

となっています。

「if oper != ” and re.match(r’!|!’, oper):」では、ルール上「!」で始まる内容だった場合に反応するようにしたいので、それ以外の場合は何もしないようにしています。(色々横着するために、try/exceptionを使ってます。もっとスマートな方法があると思いますので参考程度に。)

ツイート内容に「おみくじ」を含んでいた場合は、「『大吉』でーーす!」といったメッセージを返信し、それ以外の場合は実装していないので、「すいません。よくわかりません。」を返信するようにしています。

最後にapi.update_status関数でツイートに返信を行いますが、返信メッセージの内容として、返信ツイート相手のscreen name+メッセージという形式にしてあげる必要があります。

  • 第1引数:「’@%s %s’ % (status.user.screen_name’], reply)」で返信メッセージを指定
  • 第2引数:返信するツイートのIDをstatus.idとして指定

ここまでで自動返信の処理ロジックができます。

ツイート待ち受け

me = api.get_user(screen_name='infomisc')
flist = []
flist.append(me.id_str)

myStreamObj = MyStream(API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
myStreamObj.filter(follow=flist)

Pythonプログラムを起動している間はツイートを待ち受けられるようにします。

ツイートを待ち受ける対象のユーザは、今回は自分のみ(@infomiscのみ)としています。このためflistに追加しているのはme.id_strのみです。他のユーザのツイートも待ち受けたい場合、flistに追加してあげることで監視できるようになります。

「myStreamObj.filter(follow=flist)」を実行して、flistで指定したユーザに対するツイートを待ち受けられるようになります。filterには特定の単語のみをフィルターするようなオプションがいくつか存在しますので、用途によって追加します。

プログラム実行後、コンソール上は待ち状態となり、ツイートされると画面上にメッセージを表示するようにしています。終了したい場合は、Ctrl-Cで強制的に停止してください。

コメント

タイトルとURLをコピーしました