maRkの

キャンペーンだとか、Chess.appについてのなにか

はてなブログで同じカテゴリーの新着記事表示 (YQL使用)

Google Feed API が一時的にストップ(かどうかは分からない)するといった事象があり、一部にて混乱がおこっていました。

ここのブログでも使っていたので、影響を受けていたわけで。

astone.jeez.jp

復活したとはいえ、今後もいつ止まるのかもわからないですから、他に切り替えるということで対処しました。

オンズ » 【jQuery】緊急案件:Google Feed API が廃止になっているので代替案を紹介します。

Google Feed API のメリットは、管理にコストがかからない、というのがあります。自前でフィードの処理、キャッシュなどすれば、突然のサービス終了という心配からは解放されますが、アクセス数の多少によらず定期な監視|管理は必要でしょう。

というわけで、最初から自前でする気がないので、YQL を使用して結果を返す、というのでやってみました。

YQL Console

いきなり、作成に行きますが、YQLコンソール上で以下のようなクエリで実行しますと、複数カテゴリーのRSSより新着記事を日付順で7件分取得できます。

見やすくするため改行入れてます。このブログの「はてなブログ」、「どうでもいい」カテゴリのRSSです。

select * from feed where url in('http://tsuredureweblog.hatenadiary.jp/rss/category/%E3%81%AF%E3%81%A6%E3%81%AA%E3%83%96%E3%83%AD%E3%82%B0',
'http://tsuredureweblog.hatenadiary.jp/rss/category/%E3%81%A9%E3%81%86%E3%81%A7%E3%82%82%E3%81%84%E3%81%84')
 limit 7| sort (field="date",descending="true")

で、これをはてなブログ側ではJSONPで受け取ります。
表示する場所は、記事下あたりとします。

<h3>同じカテゴリーの新着記事</h3>
<div id="recent-same-categories"></div>

下記は、即時関数の内部です(人によって書き方が違う場合があるので)

まずは、記事が属するカテゴリーのURLを取得して、文字列置換で rss のURLにします。この例ではRSS2.0の方のURLを指定するようにしています。 URLの「archive」 の文字が 「rss」となる

  var cat = $('div .entry-categories a, div.categories a');
  if (cat) {
    var feed = '';
    for (var i = 0; i < cat.length; i++) {
      feed += '\'' + $(cat[i]).attr('href').replace('/archive/category/', '/rss/category/').toString() + '\'';
      if (i != (cat.length) - 1) {
        feed += ',';
      }
    }
  } else {
    return;
  }

なお、YQLの url in() は、引用符で囲まれて、カンマ(,)区切りになっていないと正しい結果を返してくれませんでした。
追記: スマートフォン版のカテゴリーリンクのセレクターがPC版と違うことに気がつかなかったので直しました。(metaタグにカテゴリー名あるのでそこから取得する手もあるんですが)

先ほどのクエリを使用します。

  var query = 'select * from feed where url in (' + feed + ') limit 7| sort(field="date",descending="true")';

あとは、 $.ajax() から YQLを指定して、JSONを解析して結果を整形して返します。
これは簡易的なものなので、実用にはエラー処理とか、出力の仕方にもう少し手を加える必要があります。

  $.ajax({
    type: 'GET',
    url: 'http://query.yahooapis.com/v1/public/yql',
    dataType: 'jsonp',
    jsonp: 'callback',
    data: {
      q: query,
      format: 'json'
    },
    error: function() {
      $('#recent-same-categories').append('<p>読み込み失敗</p>');
    },
    timeout: 5000,
    success: function (data) {
      var $_this = data.query.results.item;
      var html = '<ul>';
      $($_this).each(function () {
        if (this.link !== undefined) {
          html += '<li><a href="' + this.link + '">' + this.title + '</a></li>';
        }
      });
      html += '</ul>';
      $('#recent-same-categories').html(html);
    }
  });