Subscribed unsubscribe Subscribe Subscribe

全裸botはタイムラインの早さに合わせて呟く

Python GoogleAppEngine

全裸botは23分毎に呟く - すぎゃーんメモというのを書いたばかりだけど、変更した。
多くのヒトが呟いている昼間も、夜更かししているヒトだけが呟いている夜中も、同じ頻度でzenrize(他人の発言を拾ってきて全裸にしてPOST)するのは不自然。
タイムラインの速度に合わせてzenrize頻度を変えてくれるのが理想だ。


…ということを考えていたところ、id:yuroyoroさんから「cronは毎分実行するようにして、指定した時間まではそれをスルーし続けるように設定すればアプリ内で次の実行時間を調節できるんじゃね?」というようなアドバイスをいただいたので、さっそく作ってみた。
だいたいこんなカンジ。

import logging
import urllib
from datetime import datetime
from django.utils import simplejson
from google.appengine.api import memcache
from google.appengine.api import urlfetch

ZENRIZE_COUNT = 'zenrize_count'

...

    # 発言を拾って全裸にする
    def zenrize(self):
        cache = memcache.decr(ZENRIZE_COUNT)
        if cache:
            logging.debug('count: %d' % cache)
            return

        url = 'http://twitter.com/statuses/friends_timeline.json?count=50'
        result = urlfetch.fetch(
            url     = url,
            headers = self.auth_header,
            )
        logging.debug(result.status_code)
        if result.status_code == 200:
            statuses = simplejson.loads(result.content)

            # 次の実行時間を決定する
            format = '%a %b %d %H:%M:%S +0000 %Y'
            first = datetime.strptime(statuses[ 0]['created_at'], format)
            last  = datetime.strptime(statuses[-1]['created_at'], format)
            logging.debug('first : %s' % first)
            logging.debug('last  : %s' % last)
            logging.debug(first - last)
            memcache.set(ZENRIZE_COUNT, (first - last).seconds / 60)

            ...
  1. friends_timelineから50件を取ってくる
  2. 1件目と50件目の時間差を取得する
  3. この時間差(単位:分)をmemcacheに格納
  4. この値を次の実行までのカウントダウンに使い、毎回実行されるごとにデクリメントする
  5. 値が0になるまでは何もせずにメソッドは終了
  6. 値が0になれば 1. に戻りまた新しいカウントダウン値を取得する

という流れ。


memcacheの値が何らかの要因で消えてしまっても取り直すだけなので、ちょっとイレギュラーに頻度が上がる程度で済むんじゃないだろうか。
実験してみたカンジでは、現在の170 followerで、午前0時付近だと30分くらい、午前1時付近だと40分くらい。日中だとどうなるか、様子をみつつ調整しようと思います。