〈追記 2019年1月〉 残念ながら YQL終了のアナウンス がありました。
On Jan. 3, 2019, YQL service at http://query.yahooapis.com will be retired. YQL based services that use http://query.yahooapis.com, including users of http://datatables.org, will no longer operate. Yahoo Weather API users see the tweet below for info about continuing your service.
— Y! Developer Network (@ydn) December 31, 2018
とっても便利だった Google Feed API ですが、復活劇(猶予期間の延長)を経て 2016年12月15日以降は動かなくなるとのアナウンス がありました。
外部ブログのフィードを埋め込んでいるサイトをどうしようかと「google feed api alternative」でググると「Use Yahoo's YQL API」とのアドバイスをみつけたので、YQL API について調べてみました。
ちなみに、「google feed api 代替」でググると
- 有志が作成されたライブラリを使う
- Googleスプレッドシートを使う
- PHPでがんばる
などの選択肢があがっていました。
流れ
- YQL (Yahoo Query Language) とは
- YQL API について調べる
- Google Feed API から YQL API へ
- 表示の調整とか
1. YQL (Yahoo Query Language) とは
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 を開きます。
「show tables」と表示されているところがYQLのSELECTステートメントを記述する場所です。
今回はブログのRSSフィードのデータが欲しいので、左の data から rss を選びます。
ステートメントが自動で置き換わりました。
select * from rss where url='フィードのURL'
が基本形です。
URLをフィードを取得したいものに書き換え、JSON形式が選択されていることを確認して「Test」ボタンを押します。
selectの後の「*」はワイルドカードです。次のようにデータを指定して取得することもできます。
select title,link,description from rss where url='フィードのURL'
取得データを見てみる
「Formatted View」の中身を見ると、どんなデータが取得できるか確認できます。
データは階層(ドットシンタックス)になっています。「Tree View」タブに切り替えると階層がわかりやすいです。
itemの中身がブログの1記事にあたります。
例えば:ブログのタイトルはこんな感じ。
query.results.item.title
3. Google Feed API から YQL API へ
では、なんとなく解ったところでAPIを移行してみます!
<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の利用制限についてメモしておきます。
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 を使う。
参考サイト
- Google Feed API | Google Developers
- YQL - Yahoo Developer Network
- javascript - Loading RSS feed with AJAX: alternatives to Google Feed API? - Stack Overflow
- XMLのWebAPIを爆速で使いこなせるフレームワーク - Yahoo! JAPAN Tech Blog
- YQL×JSONPでクロスドメイン制約を超え、要素を取得するハナシ | 戯言Vestige++
- YQLを使用してWordPressのRSSをjsonで取得してjQueryで表示する | webOpixel