Twitter botをちょっと改良
どうやらAPI経由で投稿したとき最近10ポスト以内に同じ内容のものがあると403になってしまうらしいので、ちょっと改善してみました。
from google.appengine.ext import db class PostLog(db.Model): content = db.StringProperty() date = db.DateTimeProperty(auto_now_add=True) # 自動的に class RepPostChecker: #重複ポストがある場合は1を、ない場合は0を返す def check(self, s): g = db.GqlQuery("SELECT * FROM PostLog") l = [g.content for g in g] switch = 0 for i in l: if i == s: switch = 1 break; return switch # データベースに登録された履歴が10に達していたら一番古い記録を削除してから追加 def rec(self, s): g = db.GqlQuery("SELECT * FROM PostLog") l = [g.content for g in g] if len(l) == 10: a = db.GqlQuery("SELECT * FROM PostLog ORDER BY date ASC LIMIT 1") db.delete(a) s = PostLog(content=s) s.put()
これを、
repcheck = RepPostChecker.RepPostChecker() while 1: text = s[random.randint(0, len(s)-1)] if repcheck.check(text) == 0: repcheck.rec(text) break; twitter.post(text)
こんな感じで使います。
投稿する文章をランダムに選択したあと、それをcheck()関数に渡して直近10件の記録に一致するものがないかチェックします。一致する物があった場合もう一度選択。一致しないものが選ばれるまで繰り返し、重複チェック用のデータベースに登録したあとTwitterにポスト。
ただ、これだとランダムに決定するたびにデータベースにリクエストすることになってちょっと効率が悪いことに気づいたので、以下のように修正。
from google.appengine.ext import db class PostLog(db.Model): content = db.StringProperty() date = db.DateTimeProperty(auto_now_add=True) # 自動的に class RepPostChecker: def __init__(self): g = db.GqlQuery("SELECT * FROM PostLog") self.l = [g.content for g in g] #重複ポストがある場合は1を、ない場合は0を返す def check(self, s): switch = 0 for i in self.l: if i == s: switch = 1 break; return switch # データベースに登録された履歴が10に達していたら一番古い記録を削除してから追加 def rec(self, s): if len(self.l) == 10: a = db.GqlQuery("SELECT * FROM PostLog ORDER BY date ASC LIMIT 1") db.delete(a) s = PostLog(content=s) s.put()
あらかじめ初期値としてデータベースの内容を変数に収納しておけば一回で済みますね。(って、今見たら二回あるじゃん。あらかじめORDER BY date ASC
で取得しておけば本当に一回で済みそうですね。そのうち直そう)
これで403返されることはなくなります、と言いたいところですが実はこれだけじゃダメで、記録開始する以前のポストを履歴に登録する作業が必要だったのですが、それは手動でやりました。TwitterのAPIから投稿内容を取得して記録する、という処理を書いたほうが勉強にはなった気がする。