2008年6月14日土曜日

Google App Engine: まさに今、流行っていること

このブログ記事をはてなブックマークに追加

急上昇キーワード - 思いつきLab.でGoogle Trendの急上昇ワードを取得するAPIを知ったので、急上昇ワードを表示させるウェブアプリを作ってみた。

まさに今、流行っていること

オリジナルでは表示されない、変動の矢印、順位、前回の順位、それにスコアなどの表示を入れて、PCで見やすいものにした。さらに、Googleでキーワード検索、画像検索、Wikipediaで用語を調べられるようにした。

内容は大したものではないが、問題になったのは、xml.dom.minidomのparseだ。ローカル環境では、pyexpatがimportできず、エラーが出て実行できないのだ。サーバ側では問題ないのに。少し調べたところ、SDK1.0.2でいったん直ったらしいが、最新のSDK1.1.0ではまたエラーが出るようになったみたいだ。正式にリリースされたGoogle App Engineではあるが、SDK周りはまだbuggyな感じだなぁ。

処理部分のクラスの実装は以下の通り。あまり考えずにざっと書いたので汚いかも?

class Trend(webapp.RequestHandler): def get_text(self, nodelist): rc = "" for node in nodelist: if node.nodeType == node.TEXT_NODE: rc = rc + node.data return rc.strip() def handle_trend(self, trend): items = trend.getElementsByTagName("item") update = self.get_text(trend.getElementsByTagName("update")[0].childNodes)[:19] t = time.strptime(update, "%Y-%m-%dT%H:%M:%S") delta_update = (datetime.datetime.utcnow() - (datetime.datetime(t[0], t[1], t[2], t[3], t[4], t[5]) + datetime.timedelta(hours=7))).seconds / 60 return self.handle_items(items), delta_update def handle_items(self, items): data = [] for item in items: data.append(self.handle_item(item)) return data def handle_item(self, item): data = {} # query, rank, prev_rank, score, snippet, src for node in item.childNodes: if node.nodeType == node.ELEMENT_NODE: data[node.nodeName] = self.get_text(item.getElementsByTagName(node.nodeName)[0].childNodes) if node.nodeName == "query": data["urlencode_query"] = urllib.quote_plus(data[node.nodeName].encode("utf-8")) elif node.nodeName == "snippet": data["src"] = node.getAttribute("src") rank = int(data["rank"]) if data.has_key("prev_rank"): prev_rank = int(data["prev_rank"]) else: prev_rank = 1000 if rank < prev_rank: data["arrow"] = "<span style=\"color: red;\">↑</span>" elif rank > prev_rank: data["arrow"] = "<span style=\"color: blue;\">↓</span>" else: data["arrow"] = "←" return data def get(self): r = urlfetch.fetch("http://www.google.com/m/services/trends/get") dom = minidom.parseString(r.content) data, update = self.handle_trend(dom) template_values = { "data": data, "update": update, } path = os.path.join(os.path.dirname(__file__), "trend.html") self.response.out.write(template.render(path, template_values))

そして、テンプレートの表示部分は以下のようにした。

{% for d in data %} <div> <h2>{{ d.arrow }} {{ d.rank }} ({% if d.prev_rank %}{{ d.prev_rank }}{% else %}-{% endif %}) <a href="{{ d.src }}">{{ d.query }}</a><span style="font-size: x-small;">{{ d.score }}</span></h2> <p style="color: rgb(20%, 20%, 20%); text-indent: 16px; line-height: 140%;">{{ d.snippet }}</p> <p style="text-align: right;"><a href="http://www.google.com/search?q={{ d.urlencode_query }}">検索</a> | <a href="http://images.google.com/images?hl=ja&q={{ d.urlencode_query }}&gbv=2">画像</a> | <a href="http://ja.wikipedia.org/wiki/{{ d.urlencode_query }}">用語</a></p> </div> {% endfor %}

追記(12/1):

しばらく前から英語版になっていたのを日本語版に修正。http://www.google.com/m/services/trends/gethttp://www.google.co.jp/m/services/trends/getに変更した。ついでに夏時間対策も。

0 コメント: