GAE/Pでフォロワーの増減確認
前回の記事(フォロワーの増減を確認する - void*)は、shellで動かすことを目的として作ったもので、驚くことに、id:tyru 氏がcronで実行できる(Check Twitter's follower (via http://d.hatena.ne.jp/ykot/20110228/1298879383) · GitHub)ようにしてくれていますので、実際にお使いになる場合は、そちらを使用したほうが効率的かと思います。スクリーンネームでの表示になっていますしね。素敵です:)
今回、少し調子に乗って同じような仕組みでGAEで動かせるようにしてみました。いまさら、GAEの説明は不要だとは思いますので、わからない方は適当にググッてみてください。GAEは、自前マシンを必要としないですし、何よりマシンメンテナンスが必要ない、という点において優れています。この程度のスクリプトなら、無料の範囲なのもすばらしいです。とか、偉そうなことを書いていますが使い始めたばかりで、おもちゃ代わりに遊んでいるだけで、全然解ってないです。最低限動くよって状態ですので、ご指摘などありましたら、ぜひ。
#!/usr/bin/env python # -*- coding: utf-8 -*- from google.appengine.ext import webapp,db from google.appengine.ext.webapp import util from google.appengine.api import urlfetch from google.appengine.api import mail from django.utils import simplejson class Follower(db.Model): uid=db.StringProperty() followers=db.TextProperty() class FollowerHistory(db.Model): uid=db.StringProperty() followers=db.TextProperty() entry_dt=db.DateTimeProperty(auto_now_add=True) class MainHandler(webapp.RequestHandler): def get(self): for follow in Follower.all(): self.response.out.write( u"<a href=./%s>%s<br>" % (follow.uid, follow.uid )) class FollowerHandler(webapp.RequestHandler): def get(self, uid): url = "http://api.twitter.com/1/followers/ids/" + uid + ".json" # retry 10回 for r in range(10): result = urlfetch.fetch(url) if result.status_code != 200: self.response.out.write( u"%s twitter api error(%d)" % (uid, result.status_code) ) else: break if result.status_code != 200: return self.response.out.write( u"%s follower check<br>" % uid) # JSON結果から、list生成 newlist=simplejson.loads(result.content) # datastoreから、JSONデータを取得 follow = Follower.gql('WHERE uid = :1', uid).get() if follow is None: # データストアに存在しない=新規.比較なし Follower(uid=uid,followers=result.content).put() FollowerHistory(uid=uid,followers=result.content).put() return # 比較 oldlist=simplejson.loads(follow.followers) newset=set(newlist) oldset=set(oldlist) follow_list="" for i in newset - oldset: follow_list += "follow:%s\n" % i for i in oldset - newset: follow_list += "remove:%s\n" % i # データ設定 follow.followers = result.content follow.put() b = u"...%s の現在のフォロワーの数:%d" % (uid, len(newlist)) self.response.out.write( u"%s<br>%s" % (follow_list, b) ) if follow_list != "": # 差分あり FollowerHistory(uid=uid,followers=follow.followers).put # 差分があった時、メールを送信 body_text = follow_list + b mail.send_mail(sender = "foo@example.com", to = "bar@example.com", subject = "%s followers check" % uid, body = body_text.encode('utf-8'), ) def main(): application = webapp.WSGIApplication([('/', MainHandler), ('/([-\w]+)', FollowerHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main()
response.out.writeとかは、cron使うと必要ないのですが、デバッグとして埋め込んでいます。
http://[appname].appspot.com/[twitter uid]で、差分があった場合、メールで通知する仕組みになっています。一応、http://[appname].appspot.com/ で、一覧が出るようになっています。履歴をとっているのは、後ほど利用するためです。
色々いじっていてわかったのですが、apiは、頻繁にエラーを返すので、retryをするようにしています。
また、下記のメール設定を変更してやれば、メール送信できるようになります。foo@example.com、bar@example.comを適当に変更してご使用ください。
mail.send_mail(sender = "foo@example.com", to = "bar@example.com", subject = "%s followers check" % uid, body = body_text.encode('utf-8'), )
cron.yamlで、cron設定しておけば自動的に実行されます。5分おきとかなら、こんな感じです。差分があった場合に、メールで通知してくれます。
cron: - description: follower chenge check job url: /ykots schedule: every 5 minutes
簡単ですね ;)
ちなみに、既知のバグに、フォロワーの数が多いとエラーになるというのがあります。これは、Datastoreの容量制限に引っかかってしまっているためです。それほど試していないのですが、感覚としては、10000から20000ぐらいのフォロワーがいるとエラーになるみたいです。しばらくしたら、そのあたりも対応していく予定です。