Google Feed API から YQL API へ移行したお話

  • 36
    いいね
  • 1
    コメント

とっても便利だった Google Feed API ですが、復活劇(猶予期間の延長)を経て 2016年12月15日以降は動かなくなるとのアナウンス がありました。

外部ブログのフィードを埋め込んでいるサイトをどうしようかと「google feed api alternative」でググると「Use Yahoo's YQL API」とのアドバイスをみつけたので、YQL API について調べてみました。

ちなみに、「google feed api 代替」でググると

  • 有志が作成されたライブラリを使う
  • Googleスプレッドシートを使う
  • PHPでがんばる

などの選択肢があがっていました。

流れ

  1. YQL (Yahoo Query Language) とは
  2. YQL API について調べる
  3. Google Feed API から YQL API へ
  4. 表示の調整とか

1. YQL (Yahoo Query Language) とは

YQL - Yahoo Developer Network

yql_00.png

YQLとは米Yahoo! Developer Networkが提供している、ありとあらゆるWeb上のリソースにアクセスすることができる開発者向けのサービスです。

文法はSQLのようで独特ですが、要約すると

  • XML、HTML、RSS、CSVなどをJSONPに変換
  • WebAPIレスポンスの加工
  • キャッシュ機能つき 登録などをしなくても使える(利用制限等についてはYQL公式サイトをご参照ください)

こういった機能を持つ、汎用的なプロキシサービスです。

簡単に言うと

「YQLというものを使うと、XMLをJSONPに変換して扱えるようになる」

ということらしいです。便利っぽい!

参考)XMLのWebAPIを爆速で使いこなせるフレームワーク - Yahoo! JAPAN Tech Blog

なぜJSONP?

異なるドメインのデータを引っ張ってくるのに、XMLHttpRequest ではブラウザやサーバのクロスドメイン制約に引っ掛かるため、JSONP を使いましょう、ということらしいです(ざっくり

2. YQL API について調べる

YQL、日本ではあまりメジャーではないみたいですね(日本語のドキュメントがないから?
わたしは先人の知恵(参考サイト)に肖りながら進めてゆきます!

YQL Console を見てみる

まず YQL Console を開きます。

yql_01.png

show tables」と表示されているところがYQLのSELECTステートメントを記述する場所です。
今回はブログのRSSフィードのデータが欲しいので、左の data から rss を選びます。

yql_02.png

ステートメントが自動で置き換わりました。

select * from rss where url='フィードのURL'

が基本形です。
URLをフィードを取得したいものに書き換え、JSON形式が選択されていることを確認して「Test」ボタンを押します。

selectの後の「*」はワイルドカードです。次のようにデータを指定して取得することもできます。

select title,link,description from rss where url='フィードのURL'

取得データを見てみる

「Formatted View」の中身を見ると、どんなデータが取得できるか確認できます。

データは階層(ドットシンタックス)になっています。「Tree View」タブに切り替えると階層がわかりやすいです。

yql_03.png

itemの中身がブログの1記事にあたります。

例えば:ブログのタイトルはこんな感じ。

query.results.item.title

3. Google Feed API から YQL API へ

では、なんとなく解ったところでAPIを移行してみます!

表示用HTML
<div id="feed"></div>

Google Feed API

<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
    google.load('feeds', '1');

    function initialize() {
        var feed = new google.feeds.Feed('<!-- BEGIN_MODULE Blog_Field -->{blogRssFeedUrl}<!-- END_MODULE Blog_Field -->');
        feed.setNumEntries(1);
        // feed.includeHistoricalEntries();
        feed.load(function(result) {
            if (!result.error) {
                var container = document.getElementById('feed');

                for (var i = 0; i < result.feed.entries.length; i++) {
                    var entry = result.feed.entries[i];

                    var dd = new Date(entry.publishedDate); // now
                    var yearNum = dd.getYear();
                    if (yearNum < 2000) yearNum += 1900;
                    var m = dd.getMonth() + 1;
                    if (m < 10) {
                        m = '0' + m;
                    }
                    var d = dd.getDate();
                    if (d < 10) {
                        d = '0' + d;
                    }
                    var date = yearNum + '.' + m + '.' + d;

                    imgsrc = entry.content.match(/src="(.*?)"/igm);

                    container.innerHTML += '<article class="js-biggerlink">' + '<img ' + imgsrc + ' alt="" class="img-responsive" />' + '<h2><span class="label label-lightgray">Blog</span>' + entry.title + '</h2>' + '<p class="small">' + date + '</p>' + '<p class="feed-content">' + entry.contentSnippet.substring(0, 100) + '...</p>' + '<p><a href="' + entry.link + '" class="btn btn-primary-outline btn-block" target="_blank">View details <i class="fa fa-chevron-right"></i></a></p>' + '</article>';
                }
            }
        });
    }
    google.setOnLoadCallback(initialize);
</script>

こんな感じのスクリプトでした。
*フィードのURLにはCMSの変数が入っています

置き換えてみます。

YQL API

<script type="text/javascript">
    $(function(){
        $.getJSON("https://query.yahooapis.com/v1/public/yql?callback=?", {
            q: "select * from rss where url = '<!-- BEGIN_MODULE Blog_Field -->{blogRssFeedUrl}<!-- END_MODULE Blog_Field -->'",
            format: "json"
        }, function(json) {
            var container = document.getElementById('feed');

            for (var i = 0; i < json.query.results.item.length; i++) {
                var entry = json.query.results.item[i];

                var dd = new Date(entry.date); // now
                var yearNum = dd.getYear();
                if (yearNum < 2000) yearNum += 1900;
                var m = dd.getMonth() + 1;
                if (m < 10) {
                    m = '0' + m;
                }
                var d = dd.getDate();
                if (d < 10) {
                    d = '0' + d;
                }
                var date = yearNum + '.' + m + '.' + d;

                imgsrc = entry.encoded.match(/src="(.*?)"/igm);

                container.innerHTML += '<article class="js-biggerlink">' + '<img ' + imgsrc + ' alt="" class="img-responsive" />' + '<h2><span class="label label-lightgray">Blog</span>' + entry.title + '</h2>' + '<p class="small">' + date + '</p>' + '<p class="feed-content">' + entry.description.substring(0, 100) + '...</p>' + '<p><a href="' + entry.link + '" class="btn btn-primary-outline btn-block" target="_blank">View details <i class="fa fa-chevron-right"></i></a></p>' + '</article>';
            }
        });
    });
</script>

わたしが取得したいのはライブドアブログだったのですが、デフォルトで5件表示されました。

4. 表示の調整とか

今回は 最新の1件だけ を表示したいので、少し書き換えます。
取得するデータの件数を設定するときはステートメントに記述します。

select * from rss(オフセット数,アイテム数) where url='フィードのURL'

Remote Limits | SELECT Statement - Yahoo Developer Network

例えば、最初の3件を取得したい場合は

select * from rss(0,3) where url='フィードのURL'

もしくは、

select * from rss(3) where url='フィードのURL'

オフセットのデフォルトが0なので、省略することができます。

修正するとこんな感じに。

<script type="text/javascript">
    $(function(){
        $.getJSON("https://query.yahooapis.com/v1/public/yql?callback=?", {
            q: "select * from rss(1) where url = '<!-- BEGIN_MODULE Blog_Field -->{blogRssFeedUrl}<!-- END_MODULE Blog_Field -->'",
            format: "json"
        }, function(json) {
            var container = document.getElementById('feed');

            var entry = json.query.results.item;

            var dd = new Date(entry.date); // now
            var yearNum = dd.getYear();
            if (yearNum < 2000) yearNum += 1900;
            var m = dd.getMonth() + 1;
            if (m < 10) {
                m = '0' + m;
            }
            var d = dd.getDate();
            if (d < 10) {
                d = '0' + d;
            }
            var date = yearNum + '.' + m + '.' + d;

            imgsrc = entry.encoded.match(/src="(.*?)"/igm);

            container.innerHTML += '<article class="js-biggerlink">' + '<img ' + imgsrc + ' alt="" class="img-responsive" />' + '<h2><span class="label label-lightgray">Blog</span>' + entry.title + '</h2>' + '<p class="small">' + date + '</p>' + '<p class="feed-content">' + entry.description + '</p>' + '<p><a href="' + entry.link + '" class="btn btn-primary-outline btn-block" target="_blank">View details <i class="fa fa-chevron-right"></i></a></p>' + '</article>';
        });
    });
</script>

無事に1件だけ表示することができました。
これで、2016年12月15日が来ても慌てなくて大丈夫なはず!

〈追記〉YQL API の利用制限について

YQLの利用制限についてメモしておきます。

yql_04.png

Usage Information and Limits | Overview - Yahoo Developer Network

APIのコール数が 1時間あたり2,000まで の場合、APIキーは必要ないようです。Public Endpoint ( /v1/public/* ) が使えます。

それ以上の場合は、APIキーを取得することで 1時間あたり20,000まで 使えるようになるとのこと(1日あたり100,000まで)。OAuth Endpoint ( /v1/yql/* ) を使います。

【教訓】サイトを常時SSL化した場合、YQL Endpoint が http だとブロックされるので https を使う。

参考サイト