JavaScript
JSON
GoogleFeedAPI
YQL

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

〈追記 2019年1月〉 残念ながら YQL終了のアナウンス がありました。


とっても便利だった 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 を使う。


参考サイト