はてブのトップ記事を表示してみる

/web/javascript

Note: この記事は、3年以上前に書かれています。Webの進化は速い!情報の正確性は自己責任で判断してください。

または、如何にしてRSSからJSONを取得するか。ありふれたネタですが、久々にJS触って楽しかったので晒してみる。

...読み込み中です...

自サイトのはてブ状況は、たとえば人気エントリーなんかで確認することができますが、よく見るとRSSも配信しています。このRSSをPerlなんかで引っ張ってくれば、自ドメインのJavaScriptで解析できるわけですが、どうせなんでJSONにしてみましょう。JSONの構造はJavascriptの連想配列と殆ど同じなので(実はまったく同じではない)、いったん取得してしまえば、XMLを解析するよりぐっと楽に操作できます。

Perlスクリプト —xml2json

  1. #!/usr/local/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. use XML::Simple;
  6. use LWP::Simple;
  7. use JSON::Syck;
  8.  
  9. my $xml      = 'http://b.hatena.ne.jp/entrylist?sort=count&url=http%3A%2F%2Farchiva.jp%2F&mode=rss';
  10. my $filename = '/xxxxx/xxxxx.json';
  11.  
  12. my $document = LWP::Simple::get($xml) or die "cannot get content from $xml";
  13. my $parser   = XML::Simple->new;
  14. my $data     = $parser->XMLin($document);
  15. my $json     = JSON::Syck::Dump($data);
  16.  
  17. open( FILE, "> $filename" ) or die "$! - $filename\n";
  18. print FILE $json;
  19. close( FILE );
  20.  
  21. __END__

$xmlで指定したXML文書を元に、$filenameにJSON形式でファイルを出力します。こいつをCRON等で1日1回とか回しとけば良いでしょう。単に「print $json」して毎回呼んでも良いんですが、大して変化するわけじゃなし、書き出したファイル読む方が速い。

まあPipesとか使えばJSON出力できるようですし、必要ないっちゃないんですが、自前で用意してたほうが融通ききますしね。

  1. use CGI;
  2. my $q = CGI->new;
  3. my $c = $q->param('callback');
  4.  
  5. if ($c){
  6. print "$c($json)";
  7. }

とでも付け加えればJSONPになります。コールバック関数名で囲んでるだけですけどね。公開APIにするわけでもないので、今回は割愛。

XMLHttpRequest

  1. var xhr = {
  2. create: function(){
  3. var req = window.XMLHttpRequest
  4. ? new XMLHttpRequest()
  5. : (function(){
  6. try { return new ActiveXObject("Msxml2.XMLHTTP"); }
  7. catch(e) {
  8. try { return new ActiveXObject("Microsoft.XMLHTTP"); }
  9. catch(e) { return null; }
  10. }
  11. })();
  12.  
  13. return req;
  14. },
  15.  
  16. get: function(file,callback,type,async){
  17. var data;
  18. var req = xhr.create();
  19. async == 'false'
  20. ? req.open("GET", file, false)
  21. : req.open("GET", file, true);
  22.  
  23. req.onreadystatechange = function() {
  24. if (req.readyState == 4 && req.status == 200) {
  25. type == 'xml'
  26. ? data = req.responseXML
  27. : data = req.responseText;
  28.  
  29. if (type == 'json'){
  30. // secuity caution!
  31. data = eval("(" + data + ")");
  32. }
  33. if (typeof callback == 'function'){
  34. callback(data);
  35. }
  36. }
  37. }
  38. req.send('');
  39. }
  40. }
  41.  

今回のメイン。XHR処理は一度カプセル化しときたかったんですよね。目新しいとこは何もないですが。良いんだよ。俺のJSは基本趣味だし。サクっとテストするときには、これくらい手軽なパーツが欲しいんですよぅ。

  1. xhr.get('./hateb.json', showjson, "text", "true");

...な感じで呼び出してやります。コールバック関数(showjson。後述)は別に用意しておく必要があります。無ければ何もしない。

showjson

  1. var showjson = function(json){
  2. var data = JSON.parse(json);
  3. var targ = document.getElementById('contents');
  4. var text = '';
  5. for (var i=0; i < data.item.length; i++){
  6. if(data.item[i].link && data.item[i].title){
  7. var link = data.item[i].link;
  8. var title = data.item[i].title;
  9. title = title.replace('</.+>','');
  10. title = title.replace('<',"&lt;");
  11. title = title.replace('>','&gt;');
  12. title = title.replace(' - Archiva','');
  13.  
  14. text += '<li><a href="' + link + '">'
  15. + title
  16. + '</a>'
  17. + '<img src="http://b.hatena.ne.jp/entry/image/' + link + '" />'
  18. + '</li>';
  19. }
  20. }
  21. text = '<ol>' + text + '</ol>';
  22. targ.innerHTML = text;
  23. }

随所に手抜きが見られます(ォィ)。良いんだよ、たかだか30件。ここは見れれば良いんだし。

JSON.parse()」してる部分だけ注目。これはjson2.jsでパースしてます。JSONデータは「eval("(" + data + ")")」とでもしてやれば問題なく使えるんですが、中に妙な記述が混じっていると非常に危険なので、ちゃんとJSONなのか解析したほうがセキュリティ的に吉。今回のようなケースだと気にしなくても良いかもですが、まあサンプルということで。

Note: スパム対策が面倒なので、コメント投稿を廃止しました。以前のコメントは残します。
ご意見・ご要望はtwitter@sigwygかはてブコメントにて。