Pythonの勉強のために無料でも使えるGoogleAppEngine(以下GAE)をプラットフォームにTwitter BOTを作成して運用しています。
BOTはGoogleアラートを利用してラブライブのニュースを定期的に呟いてます。
アカウント: @ll_news_bot
ソース : GitHub
GAE SDK for PythonでBOTを運用するまでの手順を備忘録として残しておきます。
BOT仕様
今回作成したBOTの最終的な仕様は次のようになります。
- 30mごと(※1)にGoogleアラートの新エントリを呟く(9:00~23:59)
- フォローミーを呟く(18:30)
- 30mごと(※1)にフォロー返し(6:00~23:59)
- 1h毎にフォローのみの場合リムーブ(0:00~5:59)
※1 GAEにはインスタンス時間というものがあり、リクエストの処理期間中のみ時間を消費するというわけではない。
リクエストが終わった後もすぐ対応できるようアイドル状態になるが、その間も時間を消費する。
そのため、呟きとリフォローを同じ時間に行うことで無駄なアイドル時間を消費しないようにしています。
事前準備
Googleアラート
Googleアラートから新しいニュースを作成します。この時配信先を フィード にします。
環境
ローカルで開発するために次の環境を使用しています。
- Mac OS X 10.9.2
- Eclipse 4.3 + PyDev
- GoogleAppEngineLauncher 1.9.2
- Python2.7.6
- BOTアカウントの取得
- Twitter Developerへの登録
- 新しいアプリの作成とAPIキーの取得
- Permissions - アクセス権限をR/W に変更
- Test OAuth より各種認証情報を取得
GoogleAppEngine
appengine.google.com よりBOT用の新しいアプリケーションを作成します。
この時入力した Application Identifier は GAELauncherで新しいアプリを作成する際に Application ID で使用します。
外部モジュール
BOT開発にあたり次のサードパーティ製モジュールを利用しました。
Twitter APIのPythonラッパーとRSSフィードのパーサーの2種類のモジュールです。
上記のモジュールはWebアプリケーションと一緒にGAE上にデプロイしなければいけないので、
モジュールをインストール or ビルドしたあと、プロジェクト内にコピーする必要がありました。
BOT実装
作成したBOTの機能は大きく「RSSフィードから呟きの作成」と「Twitter APIの操作」になりますので、これらの処理ごとのモジュールを作成していきます。
feedモジュール
このモジュールでは feedparser モジュールを利用してRSSフィードを解析し、呟く内容を作成しています。
新着エントリがないか定期的に確認しているため、重複して呟かないように DataStore を利用しています。
class FeedFetcher(object):
'''GoogleアラートのRSSフィードをパースするためのクラス'''
def fetch_new_entries(self):
'''GoogleアラートのRSSフィードから新しいエントリを取得する。'''
# 省略
return new_entory
class Entry(object):
'''解析したエントリー情報を格納するためのクラス'''
def make_tweets(self):
'''呟き内容を作成する'''
return # 呟き
# 使い方
fetcher = FeedFetcher()
new_entries = fetcher. fetch_new_entries()
for entry in new_entries:
print entry.make_tweet()
botモジュール
このモジュールでは、python-twitterモジュールをラップし、必要なAPIを簡単に叩けるようにしています。
また、準備の時に取得したTwitterの認証情報をpython-twitter APIに渡しています。
こちらを参考にさせていただき、GAEでpython-twitterを使用する場合はキャッシュしないようにしています。
class TwitterBot(object):
'''Twitterへの呟き、ユーザのリフォローとフォロー解除を行うためのクラス'''
def tweet(self, message):
'''Twitterへ対象の内容を呟く'''
# 省略
def get_not_follow_users(self):
'''未フォローユーザのIDリストを取得する'''
return # 未フォローユーザIDリスト
def refollow(self, not_follow_id):
'''対象のユーザをフォローする'''
# 省略
# ...省略
#使い方
bot = TwitterBot()
fetcher = FeedFetcher()
bot.tweet(fetcher. fetch_new_entries[0].make_tweet)
bot.refollow(bot. get_not_follow_users()[0])
リクエストハンドラ
まずURLマッピングを行うために app.yaml ファイルを作成します。
login が admin になっていると、ブラウザ上でURLを叩いてもアカウント認証しないとリクエストが送信されないようになります。
script には モジュール名とURLマッピングを行う WSGIApplication オブジェクト名を書きます。
application: ll-news-bot
version: 8
runtime: python27
api_version: 1
threadsafe: true
handlers:
- url: /
script: tweet.app
login: admin
- url: /tweet
script: tweet.app
python側では RequestHandler を継承したクラスを作成し、get もしくは post メソッドのハンドル処理を書いていきます。
一度に大量にTwitterAPI をコールすることはありませんが、勉強のためタスクキューを使用しています。
タスクが実行されると指定したURLにPOSTメソッドのリクエストが送信されます。
class MainHandler(webapp2.RequestHandler):
def get(self):
taskqueue.add(queue_name='tweet', url='/tweet', params={'message': u'テスト'})
class TweetHandler(webapp2.RequestHandler):
def post(self):
# つぶやき処理
bot = TwitterBot()
bot.tweet(self.request.get('message')
app = webapp2.WSGIApplication([('/', MainHandler), ('/tweet', TweetHandler)], true)
タスクキューを使用するには queue.yaml を作成します。タスクキューに関する説明は次のサイトがとても参考になりました。
queue:
- name: tweet
rate: 1/s
bucket_size: 1
retry_parameters:
task_retry_limit: 0
最後にこの処理を定期的に実行させるように cron.yaml ファイルを作成します。
どのくらいの間隔で実行するか schedule で設定します。
cron:
- description: tweet task
url: /
schedule: every 30 minutes from 9:00 to 23:59
timezone: Asia/Tokyo
ローカル実行
GAELaucherアプリを使用し、ローカル環境でアプリの動作確認してみます。
作成はLauncherアプリから行えます。その際、Application IDに事前準備で予め作成しておいたアプリの Application Identifier を使用します。
実行の前にメニューから Make Symlink を実行しておく必要があります。
また、GAEが使用するポート番号を他のアプリが使用している場合は、どちらかのポート番号を変更する必要があります。
デプロイ
最後にGAELauncherを使用し、Googleのサーバーにアプリケーションをデプロイします。
その際にアカウント入力がありますので、事前準備で作成したアプリケーションに対応するGoogleアカウントを入力します。
デプロイ中に Checking if deployment succeeded. が延々と表示される場合がありましたが、これはサーバー側の問題のようです。
最後にバージョンを上げて再デプロイするかロールバックしてくださいとでますので、今回はバージョンを上げて再デプロイしたところ上手くいきました。
以上がTwitterのBOTを開発してから運用するまでの流れになります。