前回はApressのボットを作成したものの、一日2回つぶやくなどの不具合があったため、今回はその部分を改修することに。
改修してみたら予想外に大きくなってしまったが、いくつか有意義であったため、そのメモ。
■追加した仕様
■実装時に困ったことと対応
NDBまわり
以前の記事に寄せられたコメントに触発され、NDBを使ってみることに。以下の公式ドキュメントを参考にした。
NDBでのkey_nameの扱い
idと統合されたようなので、保存するときはidで指定する模様。
What's the best way to specify a key_name for App Engine NDB Model? - Stack Overflow
from google.appengine.ext import ndb class TweetHistory(ndb.Model): # idは "tweet" 固定 last_message = ndb.StringProperty() # 保存するとき history = TweetHistory(id=u'tweet', last_message=message) history.put()
NDBでのキャッシュの扱い
NDBではデータストア以外にキャッシュも使うため、キャッシュの扱いに悩んだ。今回はキャッシュを使うほどでもないため、データストアからの取得ではキャッシュは全て利用しないようにした。
history = ErrorMailHistory.get_by_id( errorType, use_cache=False, use_memcache=False )
GAEでGoogle Feed APIを使う
以下のサイトにサンプルがあったため、それを参考に組んでみた。
- JSON Developer's Guide for the Google Feed API - Google Feed API — Google Developers
- E71:PythonでGoogle AJAX Feed API を使ってみる - HiiHahWIKI - making some notes for... -
# 必須パラメータなので、呼び出し元のサーバーIPアドレスを取得する ip = os.environ['REMOTE_ADDR'] # Google Feed API での1件フェッチ url = ( u'https://ajax.googleapis.com/ajax/services/feed/load?v=1.0&q=' + u'http://www.apress.com/index.php/dailydeals/index/rss' + u'&num=1' + u'&userip=' + ip ) feed = urlfetch.fetch(url) j = json.loads(feed.content) entries = j['responseData']['feed']['entries'] for entry in entries: # entriesは1件だけのため、forの中で処理をしてしまう result = self._create_message(entry['title']) return result
Google Feed APIを使う時のIPアドレス指定
サンプルを見ると、パラメータとしてIPアドレスを渡す必要があった。
GAE環境のIPアドレスはどのように取得すればよいかを探したところ、以下の方法で取れるとのこと。
Webコピペ屋::Google App Engineで環境変数のリモートIPアドレスを取得する
import os print os.environ['REMOTE_ADDR']
メール送信時の送信者指定
自分のメールアドレスを指定したくないと考えていたところ、公式ドキュメントの中に「アプリケーションの任意の有効なメール受信アドレス(xxx@APP-ID.appspotmail.com など)です。」との記載あり。
Message Fields - Google App Engine — Google Developers
そこで、以下のように送信者のアドレスを組み立てみた(管理者アカウントへの送信は、mail.send_mail_to_adminsを使えばよかった)。
host = self.request.host splited = host.split('.') email = u'attention@' + splited[0] + u'.appspotmail.com'
■ソースコード
thinkAmi/EbooksDealoftheDayBot · GitHubへとアップ。(2012/11/8 アップ先のURLを修正)