Note: この記事は、3年以上前に書かれています。Webの進化は速い!情報の正確性は自己責任で判断してください。
または、如何にしてRSSからJSONを取得するか。ありふれたネタですが、久々にJS触って楽しかったので晒してみる。
自サイトのはてブ状況は、たとえば人気エントリーなんかで確認することができますが、よく見るとRSSも配信しています。このRSSをPerlなんかで引っ張ってくれば、自ドメインのJavaScriptで解析できるわけですが、どうせなんでJSONにしてみましょう。JSONの構造はJavascriptの連想配列と殆ど同じなので(実はまったく同じではない)、いったん取得してしまえば、XMLを解析するよりぐっと楽に操作できます。
Perlスクリプト —xml2json
#!/usr/local/bin/perl
use strict;
use warnings;
use XML::Simple;
use LWP::Simple;
use JSON::Syck;
my $xml = 'http://b.hatena.ne.jp/entrylist?sort=count&url=http%3A%2F%2Farchiva.jp%2F&mode=rss';
my $filename = '/xxxxx/xxxxx.json';
my $document = LWP::Simple::get($xml) or die "cannot get content from $xml";
my $parser = XML::Simple->new;
my $data = $parser->XMLin($document);
my $json = JSON::Syck::Dump($data);
open( FILE, "> $filename" ) or die "$! - $filename\n";
print FILE $json;
close( FILE );
__END__
$xmlで指定したXML文書を元に、$filenameにJSON形式でファイルを出力します。こいつをCRON等で1日1回とか回しとけば良いでしょう。単に「print $json
」して毎回呼んでも良いんですが、大して変化するわけじゃなし、書き出したファイル読む方が速い。
まあPipesとか使えばJSON出力できるようですし、必要ないっちゃないんですが、自前で用意してたほうが融通ききますしね。
use CGI;
my $q = CGI->new;
my $c = $q->param('callback');
if ($c){
print "$c($json)";
}
とでも付け加えればJSONPになります。コールバック関数名で囲んでるだけですけどね。公開APIにするわけでもないので、今回は割愛。
XMLHttpRequest
var xhr = {
create: function(){
var req = window.XMLHttpRequest
? new XMLHttpRequest()
: (function(){
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch(e) {
try { return new ActiveXObject("Microsoft.XMLHTTP"); }
catch(e) { return null; }
}
})();
return req;
},
get: function(file,callback,type,async){
var data;
var req = xhr.create();
async == 'false'
? req.open("GET", file, false)
: req.open("GET", file, true);
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
type == 'xml'
? data = req.responseXML
: data = req.responseText;
if (type == 'json'){
// secuity caution!
data = eval("(" + data + ")");
}
if (typeof callback == 'function'){
callback(data);
}
}
}
req.send('');
}
}
今回のメイン。XHR処理は一度カプセル化しときたかったんですよね。目新しいとこは何もないですが。良いんだよ。俺のJSは基本趣味だし。サクっとテストするときには、これくらい手軽なパーツが欲しいんですよぅ。
xhr.get('./hateb.json', showjson, "text", "true");
...な感じで呼び出してやります。コールバック関数(showjson。後述)は別に用意しておく必要があります。無ければ何もしない。
showjson
var showjson = function(json){
var data = JSON.parse(json);
var targ = document.getElementById('contents');
var text = '';
for (var i=0; i < data.item.length; i++){
if(data.item[i].link && data.item[i].title){
var link = data.item[i].link;
var title = data.item[i].title;
title = title.replace('</.+>','');
title = title.replace('<',"<");
title = title.replace('>','>');
title = title.replace(' - Archiva','');
text += '<li><a href="' + link + '">'
+ title
+ '</a>'
+ '<img src="http://b.hatena.ne.jp/entry/image/' + link + '" />'
+ '</li>';
}
}
text = '<ol>' + text + '</ol>';
targ.innerHTML = text;
}
随所に手抜きが見られます(ォィ)。良いんだよ、たかだか30件。ここは見れれば良いんだし。
「JSON.parse()
」してる部分だけ注目。これはjson2.jsでパースしてます。JSONデータは「eval("(" + data + ")")
」とでもしてやれば問題なく使えるんですが、中に妙な記述が混じっていると非常に危険なので、ちゃんとJSONなのか解析したほうがセキュリティ的に吉。今回のようなケースだと気にしなくても良いかもですが、まあサンプルということで。
Note: スパム対策が面倒なので、コメント投稿を廃止しました。以前のコメントは残します。
ご意見・ご要望はtwitter@sigwygかはてブコメントにて。