Hatena::ブログ(Diary)

好奇心の塊 このページをアンテナに追加 RSSフィード

2010-03-01

Google Ajax Feed APIでRSSを取得するとキャッシュが利用される件の解決法

| 14:58 | Google Ajax Feed APIでRSSを取得するとキャッシュが利用される件の解決法を含むブックマーク Google Ajax Feed APIでRSSを取得するとキャッシュが利用される件の解決法のブックマークコメント

概要

Web上でRSSというXML形式の「更新履歴情報」が広く使われています。

しかしjavascriptは他ドメインリソースにアクセスする事を原則的に禁じているため,他サイトのRSSを取得してホームページ上に動的に表示するのは簡単ではありません。大抵の場合は取得用のCGIを別に用意したりします。

しかしGoogleの提供しているAPIを利用すれば,javascriptを書くだけで他サイトのRSSフィードを取得する事が出来ます。(要はそれ用のサーバgoogleが貸してくれる感じ)


APIに関する詳しい話は下のURLにて

デベロッパーガイド - Google AJAX Feed API

http://code.google.com/intl/ja/apis/ajaxfeeds/documentation/


しかしこのAPIを利用すると,更新が反映されるのがとても遅い

下手をすると数日前のデータが表示され,RSSの意味が無い状態になります。

何でだろう?他の人はどうしてるんだろう?と半年ほどボケーッと考えていたのですが,

ついに解決策を見つけたので記録しておきます。


原因

まず原因ですが,javascriptRSSGoogleに要求したとき,Googleキャッシュしているデータを返しているのが原因です。

よく考えれば当たり前ですね。


対策

そのため,無理矢理キャッシュを更新させます。

RSSURLにダミークエリを追加します。たとえばフィード

http://d.hatena.ne.jp/m_ogawa/rss

ならば,

http://d.hatena.ne.jp/m_ogawa/rss?123

というように,?123という文字列を末尾に入れます。

123でも問題無いようですが,このようなダミークエリを挿入する際,

javascriptでは現在時刻の文字列を入れる事が多いようです。

そこで,

"http://d.hatena.ne.jp/m_ogawa/rss" + "?" + (new Date()).getTime()

とするのがベターのようです。

(全て参考資料から引っ張ってきています)


参考に,僕のWebサイトのソースを貼ってみます。

(ついでにコメントを読めばGoogleAPIの使い方が何となく分かる…かな?)

<script type="text/javascript" src="http://www.google.com/jsapi?key=***"></script><!--googleの提供するAPIを使うための一行-->
<script type="text/javascript"> 
//feedのバージョン指定(決まり文句のようなもの)
google.load("feeds", "1");

function initialize() {
  //フィードのオブジェクトを取得(引数のURLにダミークエリを挿入)
  var feed_hatebu = new google.feeds.Feed("http://d.hatena.ne.jp/m_ogawa/rss"+"?"+(new Date()).getTime());
  //取得するフィードのエントリ数を指定
  feed_hatebu.setNumEntries(3);
  //無名関数を使って,RSSを取得した際の動作を設定
  feed_hatebu.load(function(result) {
    if(!result.error) {
      //id="hatenablog"の空<div>を用意して,そこに要素を挿入します。
      var container = document.getElementById("hatenablog");
      //ul要素を作ります。属性も指定。
      var ul = document.createElement("ul");
      ul.setAttribute("style","margin:0;");
      //読んだエントリの数だけループ処理
      for (var i = 0; i < result.feed.entries.length; i++) {
        //li要素を作り,エントリの内容を加えます。リンクを貼ったりしつつ。
        var li = document.createElement("li");
        var entry = result.feed.entries[i];
        var strdate = createDateString(entry.publishedDate);
        var span = document.createElement("span");
        span.innerHTML="("+strdate+")";
        var a = document.createElement("a");
        var br = document.createElement("br");
        a.href = entry.link;
        a.target="blank_";
        a.appendChild(document.createTextNode(entry.title));
        li.appendChild(a);
        li.appendChild(span);
        li.appendChild(br);
        ul.appendChild(li);
      }
      //ul要素をdivに挿入するのを忘れず。
      container.appendChild(ul);
    }
  });
}
//上の関数をコールバック関数に指定。
google.setOnLoadCallback(initialize);
</scirpt>

という感じです。


(追記)

フィードURLの末尾の形によっては,上記では上手くいきません。

例えば

http://www.abc.de/new.cgi?feed=rss1

といったURLの場合です。この場合は以下のように,&でダミークエリを繋ぎます。

http://www.abc.de/new.cgi?feed=rss1&123

これでも上手くいかないケースが稀にあるようです。

その一例がgooの質問箱にあるので,挙げておきます。

Google Ajax Feed API キャッシュ騙しの方法

http://oshiete1.goo.ne.jp/qa5714958.html



注意点

キャッシュを生成しなおす(と思う)ので,読み込みが遅くなります。(ダミークエリを使う場合)

AllAboutの記事には

ただし、これらのテクニックは、あまり強制読み込み頻度が多いとキャッシュが過剰に保存されすぎるので注意が必要です。

とあります。これが具体的に何を意味しているのかはよくわかりません。

キャッシュは上書きされずに沢山作られる,ということでしょうか。

要はアクセスの多いサイトではこの方法は無理があるという認識で良いと思います。


追記1

どうやら,クエリに現在時刻の文字列を追加することによってURLが変わるため,

javascriptRSSを取得する際に逐次キャッシュを作るようです。

(厳密にはURLが違うから,というわけでは無いような気もします。

 Googleキャッシュの仕組みについてはまだよく調べていません)

たとえば1秒に1回アクセスがある場合,60秒で60回キャッシュが作られます。

まさかそんな頻度でブログを更新するわけもないので,上記のように現在時刻文字列でダミークエリを生成してしまうと大変な無駄になります。

せっかく生成したキャッシュを再利用するためには,1秒に2回以上のアクセスが必要ということになります。

そこで,現在時刻の文字列から秒数や分数を省く,或いは四捨五入のような切り捨てを行うことで若干の無駄を省くことが可能です。

これは即ち,キャッシュを本来の目的(読み込みの高速化)で利用することになります。


追記2

ダミークエリに秒数まで含むと,ページを読むのが非常に重いです。

そのため,1時間毎に更新するのが良さそうです。


(参考)Google AJAX Feed API キャッシュ騙し 〜1時間ごとver.〜

http://d.hatena.ne.jp/bass-inu/20090704/1246715391


このエントリでは月・日にち・時間の3つの間にゼロを挟むという事をしていますが,

数字を文字列に変換する目的かと思います。

javascript変数型の扱いが他の言語に比べ厳密でないため,

数字+文字列という演算をすると全て文字列になってしまいます。

そこで数字にヌル文字列を加えて数字から文字列に変換する方法がよく使われます。

結局,以下のようなソースにしました。

      var d = new Date();
      var dq = d.getMonth()+""+d.getDate()+""+d.getHours();
      var feed_hatebu = new google.feeds.Feed("http://d.hatena.ne.jp/m_ogawa/rss?"+dq);

これなら1時間毎にキャッシュが更新されるため,最初の更新時以外は読み込み速度が遅くなりません。


参考資料

Google Ajax Feed APIキャッシュ騙しを使う方法

http://www.lepracaun.info/blog/2007/06/google-ajax-feed-api-2.html

Google Ajax Feed API キャッシュ騙しの方法(再掲)

http://oshiete1.goo.ne.jp/qa5714958.html

YUI+GoogleAJAX Feed API - AllAbout

http://allabout.co.jp/internet/javascript/closeup/CU20070430A/index3.htm#4

ぽおぽお 2010/05/06 15:39 なぜ更新されないのか分からずに困っていたところでした。ありがとうございましたヽ(TωT)ノ

m_ogawam_ogawa 2010/05/06 20:32 お役に立てたようで幸いです。

とりとりとりとり 2013/07/22 21:52 何故、削除や更新が反映されないのか大分悩み、調べ、こちらに辿りつきました。
説明されていた通りコードを追加したら、ばっちり即反映されるようになりました!!
嬉しくてお礼が言いたくてコメントしました!ありがとうございました!(ToT)/~~~