When it’s ready.

出来るまで出来ない

(未完成)twitter検索のクローン で wassr検索(wassrhub) をGoogleAppEngineで作ってみる

python温泉の成果を発揮すべくGAEでアプリを作って見ようと思った。
きっかけは、なぜか2日の午後からwassrのfollowメールが急増したから。ユーザーが増えて負荷の高くなったwassrが、他の人のヒトコトを見る事が出来ない状態だったので流れもよくわからず、これは、検索作るしかないなと言う事を思いついた。

(アドレスは http://a2c.appspot.com/wassrhub です。
今は、何も表示されません。)

とりあえづ、パースとか要らなさそうなPublicのCSVを取得して、適当なFeedテーブルに入れてあげて、あとから、検索出来る様にすることにした。
今回作成したファイルは2つ。main.pyとtop.htmlになる。

作る前からの問題点で、クロールのタイミングを、自発的に出来ないポイのでとりあえづ、リクエストのある度にwassrから取得することにした。完成の暁には、外部からCronなりでたたきに行く口を作ろうと思う。

以下部分ごとに説明

import部分

必要ないのも入ってるけどコレくらいあれば事足りそう。
(今回もDjangoのお世話にならないで、webappでシンプルに作る)

#!/usr/bin/env python
#coding:utf8
import logging
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import *
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.template import Template, Context

from os import path
import urllib2
from google.appengine.api import urlfetch

モデル部分

Feedというクラスで、中身は、wassrapiから引っ張って来れる内容をそのままに、最後に取得時間を自動で付けた。

class Feed(db.Model):
  UNIQ_KEY = db.StringProperty(required=True)
  MESSAGE = db.TextProperty()
  URL = db.StringProperty()
  NICK = db.TextProperty()
  DATETIME = db.StringProperty()
  LOGINID = db.StringProperty()
  SLURL = db.StringProperty()
  created = db.DateTimeProperty(auto_now_add=True)

コントローラ部

(コメント参照)

get部分
class Top(webapp.RequestHandler):
  @login_required
  def get(self):
    url = "http://api.wassr.jp/statuses/public_timeline.csv"
    # gae のライブラリのurlfetchを使ってcsvを取得する。
    result = urlfetch.fetch(url)
    if result.status_code == 200:
      str = result.content
    else:
      str = ''
      self.response.out.write(result.status_code)
      self.response.out.write('\nwassr取得に失敗しました。\n')
      self.response.out.write(result.content)
    # 改行でスプリットして一人分を生成
    str1 = str.split('\n')
    one_feed = []
    # 以下ひとりづつ処理
    for i in str1[1:]:
      tmp_feed = i.split(',')
      # 既にDataStoreに保存されているかを確認する。
      if Feed.all().filter('UNIQ_KEY =', tmp_feed[0]).count() > 0:
        pass
      else:
        feed_ins = Feed(UNIQ_KEY = tmp_feed[0],
                        MESSAGE = tmp_feed[1].decode('utf8'),
                        URL = tmp_feed[2],
                        NICK = tmp_feed[3].decode('utf8'),
                        DATETIME = tmp_feed[4],
                        LOGINID = tmp_feed[5],
                        SLURL = tmp_feed[6])
        feed_ins.put()
    p = {}
    # すべてのFeedを新しい順ですべて取得
    p['feed'] = Feed.all().order('-created')
    self.response.out.write(template.render('templates/top.html', p))
post部分
  def post(self):
    mess = self.request.get('name')
    mess = self.request.get('mes')
    p = {}  
    print mess.encode('utf8')
    p['feed'] = Feed.all().filter('MESSAGE =', mess)
    self.response.out.write(template.render('templates/top.html', p))

View部分

<form action="/wassrhub/top" method="post">
	<input type='text' name='name'>
	<input type='text' name='mes'>
	<input type='submit' value='Search'>
</form>
<br>

{% for i in feed %}
	{{ i.UNIQ_KEY}}{{ i.MESSAGE }}<br>
{% endfor %}

main部分


def main():
  logging.getLogger().setLevel(logging.DEBUG)
  urls = [#('/wassrhub/users', UsersList),
          ('/wassrhub.*', Top)]
  application = webapp.WSGIApplication(urls, debug=True)
  wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
  main()


とりあえづ、ローカルでは続々新しいデータが取得され続ける事を確認し、検索部分を作り始めたが、どうやっても、フィルターに引っかからない。たまたま、ApiGURUなtmatsuo氏とチャットで出会ったので色々教えてもらうとTextPropertyは、インデックスが付かないので検索出来ないらしい!!なんということ!!最悪である。StringPropertyだとwassrのメッセージが入り切らないので使えない。IDだけでも検索出来れば良いと言う事に変更し、appspot.comに上げて見ることにした。deployボタン一つで配備は完了してドキドキしながらアクセスしてみると全くFeedが保存されない。特にエラーも出てないし、何が起こっているのか判らないのでloggingを設定した(tmatsuo氏にお世話になった。ありがとうです)
インポート部分に

import logging

を追加して、main()の中に

logging.getLogger().setLevel(logging.DEBUG)

これを追加すると、appspot.comの中でlogが詳細に出るようになった。
しかし、やはりエラーが出ていない。http://api.wassr.jp/statuses/public_timeline.csv のページからは、ちゃんとデータが出ている事は何度も確認した。確認の為にcsvだけコピーして、自分の別のサーバーにファイルをアップしてそこから、取得するようにしてみると、正常に動作する。

wassrから、200が返ってきてないのかと、確認の為に

self.response.out.write(result.status_code)

と書いてみるとビンゴ!503が返ってきていた。
なんで、こんなことになるのか判らないけど、wassr.jpとappspot.comの間の部分はどうしようも出来ないと諦め、今日はここまでとした。

間に別サーバーでプロキシ立てたら出来そうだけど、そんな事するんだったら、プロキシやらせてる所で全部やってしまった方が良いので、GAEの勉強にならない。と、自分に言い訳してみる。

wassrの人がappspot.comに制限かけてるとは思えないんだけどなんでこんな事になるんだろか?



アドレスは http://a2c.appspot.com/wassrhub です。
今は、何も表示されません。

追記:codereposに上げてみました。(他力本願・・orz)
http://coderepos.org/share/browser/lang/python/gae_wassrhub?rev=15072