読者です 読者をやめる 読者になる 読者になる

ApressのDeal of the Day用のbotを作ってみた (2)

Twitter GoogleAppEngine Python

前回はApressのボットを作成したものの、一日2回つぶやくなどの不具合があったため、今回はその部分を改修することに。
改修してみたら予想外に大きくなってしまったが、いくつか有意義であったため、そのメモ。

■追加した仕様

  • Apressのサイトのスクレイピングが失敗した場合、ApressのRSSからデータを拾う
  • 同じ内容は二度つぶやかないようにするため、データストア(NDB API)を使う
  • 各種エラーが発生したら、管理者宛にメールを送信する

■実装時に困ったことと対応

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を使う

以下のサイトにサンプルがあったため、それを参考に組んでみた。

# 必須パラメータなので、呼び出し元のサーバー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を修正)



■一日経過時点の使用リソース

色々と使っていますが、無料の範囲内で収まっています。