2008/06/06


このサーバではJSON::Syck::Load(YAML::Syck::LoadJSON)が動かなかった(おそらくXSコンパイルされてない)のでJSON::PPを使ってますが、使える人はJSON::Syck::Loadを使うという事で
hatenastar_mobile
# Blosxom Plugin: hatenastar mobile
# Author(s): mattn
# Version: Fri, 06 Jun 2008

package hatenastar_mobile;

use strict;
use warnings;
use vars qw($stars);
use LWP::UserAgent;
use URI::Escape;
use HTTP::Request;
use JSON::PP;

$stars = '';

my $permalink_flavour = 'htm';
my @mobile_ua = qw(UP\.Browser KDDI PDXGW DoCoMo J-PHONE L-mode Vodafone SoftBank);

sub start {
    return 1 if map { $ENV{'HTTP_USER_AGENT'} =~ /$_/ } @mobile_ua;
}

sub story {
    my($pkg, $path, $fn, $story_ref, $title_ref, $body_ref) = @_;
    return 0 if $ENV{'PATH_INFO'} !~ /\.$permalink_flavour$/;

    eval {
        my $uri = 'http://s.hatena.ne.jp/entries.json?uri=' . URI::Escape::uri_escape("$blosxom::url$path/$fn.$permalink_flavour");
        my $ua = LWP::UserAgent->new;
        my $req = HTTP::Request->new(GET => $uri);
        my $res = $ua->request($req);
        $res->is_success or return 0;
        my $json = decode_json( $res->content );
        my @sts = @{$json->{entries}->[0]->{stars}};
        for my $st (@sts) {
            $stars .= '<img src="http://s.hatena.ne.jp/images/star.gif" title="' . $st->{name} . '" />'
        }
    };
    1;
}
パーマリンクとなるflavour名をpermalink_flavourに指定し、flavourに"$hatenastar_mobile::stars"を入れると表示されます。
Posted at by



2008/06/02


GoogleからjQueryやdojoがロード出来るAjaxライブラリが公開されました。

The AJAX Libraries API is a content distribution network and loading architecture for the most popular open source JavaScript libraries. By using the Google AJAX API Loader's google.load() method, your application has high speed, globaly available access to a growing list of the most popular JavaScript open source libraries including:

http://code.google.com/apis/ajaxlibs/
でも、リンク先に載ってるコード、良く見たら動かないよ><
googl ajax library typo
正しくは <script src="http://www.google.com/jsapi"></script>
<script>
  var renderResults = function(results) {
      $.each(results, function(index, item) {
        $('#result')
          .append('<div id="result' + index + '"></div>');
        $('#result' + index)
          .append('<a href="' + item.url + '">' + item.title + '</a>')
          .append('<div>' + item.content + '</div>')
          .append('<span>' + item.visibleUrl + '</span>')
          .css('padding', '0.5em');
        $('#result' + index + ' div')
          .css('border', '1px dotted gray')
          .css('width', '500px')
          .css('padding', '1em')
          .append('<span>');
        $('#result' + index + ' span')
          .css('color', 'green')
          .css('margin-left', '1em');
      });
  }

  // Load jQuery
  google.load("jquery", "1");

  // on page load complete, fire off a jQuery json-p query
  // against Google web search
  google.setOnLoadCallback(function() {
    $.getJSON("http://ajax.googleapis.com/ajax/services/search/web?q=google&v=1.0&callback=?",

      // on search completion, process the results
      function (data) {
        if (data.responseData.results &&
            data.responseData.results.length>0) {
          renderResults(data.responseData.results);
        }
      });
    });

</script>
<div id="result"></div>
こんな感じになります。あと、visualization等の場合はgoogle.loadの第3引数が有効で"callback"の記述が出来たのですが、jQueryやdojo等サードパーティな物では動かなかった。残念。
ちなにみ上のコードを動かすと、こんな感じになります。

続きを読む...

Posted at by




これ、すごいっす。
The Memcache API - Google App Engine - Google Code

High performance scalable web applications often use a distributed in-memory data cache in front of or in place of robust persistent storage for some tasks. Google App Engine includes a memory cache service for this purpose.

http://code.google.com/appengine/docs/memcache/
何が凄いって仕様が凄い。
通常のset/getの他、dictとして格納出来るset_multi/get_multiもある。Tagtterの様にタグ毎にキャッシュしたい場合には持って来いなAPIです。
どうやらdangaをベースにしている様で、LiveJournalsourceforge、さらにはWikiPediaでも使われているライブラリらしいです。

さて、今日Tagtterにこのmemcache APIを使ってみました。
使い方としてはページをそのまま!Tagtterの場合、動的なコンテンツと言えばタグ、Vote、ユーザですが、これらが変更されない限りトップページタグページは変る事は無いのです。他の情報はjavascript(jQuery)で動的に取得しており、サーバには格納されていません。
どんなに大胆な使い方かと言うと
class TopPage(webapp.RequestHandler):
  def get(self):
    cache = memcache.get('tagtter_top_page')
    if cache:
      # キャッシュがあるならそのまま出力
      self.response.out.write(cache)
      return

    ・・・ 巨大なデータ処理 ・・・

    path = os.path.join(os.path.dirname(__file__), get_template(self))
    cache = template.render(path, template_values)
    # キャッシュに溜め込む
    memcache.set('tagtter_top_page', cache, cache_time)
    self.response.out.write(cache)

class AddTagsAPI(webapp.RequestHandler):
  def get(self, username):

    ・・・ タグの追加処理 ・・・

    # 結果を出力
    dump_json(self, { 'status': 'ok', 'message': 'done' })
    # キャッシュをクリアしてやる
    memcache.flush_all()
上記の様に、キャッシュがあればそのまま出力し、タグが追加されればキャッシュをクリアするという方法。
おかげでトップページタグページの表示速度が激変しました。
但し、ユーザ一覧ページ等は、pageというパラメータにより出力する内容が異なる為、このままでは対応出来ません。やっちゃうとどんどん同じページが表示されてしまいます。
今のところ、トップページとタグページにしか取り入れていませんが今後少しずつ取り入れて行きたいと思います。

ところで、公開されたAPIのもう一つImages APIも使ってみました。
使い方は簡単。
from google.appengine.api import images

...

image = images.Image(data) # input data
image.resize(100, 100)
image.rotate(90)
data = image.execute_transforms(output_encoding=images.JPEG)
現状、合成したり90度単位でない回転等は出来ませんが、コレ使えばなんでもありちゃんかいっと思った。いずれやる。

動いている物は以下
Image API Test
Posted at by