Home

日記
blogmapの巡回がはてなダイアリーに偏っている? (01:14)Edit

blogmapの「『『ユリイカ』2005年4月号特集*ブログ作法』(青土社)のネットでの評判」が?Dだらけだったという件について』のコメント欄のやりとりあたりへの反応。

blogmapは、各blogサイトの更新時刻情報を取得し、それを元に巡回をしています。はてなダイアリー上にあるサイトの更新時刻情報は、

からかなり確実に取れるんですが、それ以外のサイトに関しては、ping.bloggers.jpとかbulkfeedsとかの公開pingサーバー経由で更新情報を取得しているんで、それらにpingを飛ばしていないサイトは巡回対象から外れます。

blogmap自身でも公開pingサーバー(http://1470.net/api/ping)を用意しているんで、ここにpingを飛ばしてもらえると一番確実に巡回対象になります。

ということで、blogmapの情報ソースにはてなダイアリーの情報がやたらと多いのは、巡回のきっかけになる更新時刻情報の精度が高いから、というのが第一の理由でしょう。

あと、最近はてなダイアリーはRSSのdescriptionに含まれる情報量を増やせるようにしました。また、もともと日記系ツールということで、1エントリー(<h3>タグ間)が短くなりがちな分、他のblogツールと比べるとdescriptionの中に本文中の主要な要素(ISBNとかURLとか)が含まれやすくできています。

一方、通常の(MT系みたいな)blogサイトだと、1エントリーは長文になりがちで、その冒頭をdescriptionとして取り出した場合に、blogmapの解析対象要素がそこに含まれないという場合が出てきます。

たとえば、「絵文録ことのは」がblogmapのユリイカに言及したサイトとして表示されない=blogmapで巡回されていないという話が出てますけど、これは巡回されていないんじゃなくて、絵文録のRSSの該当エントリーのdescriptionにユリイカのISBNコードが含まれていないんで解析できなかった、というのが正解です。

blogmapは1470.netに移転したタイミングで、HTMLではなくRSSのdescriptionもしくはcontent:encodedのみを解析するようになったんで、本文中でふれている話題でも、RSSに載っていなければなかったものと見なされます。旧バージョンではHTMLを直接解析していたんで、本文中に書かれていればすべて解析対象になったんですけど。

ちなみにblogmapが2005/3/1以降に巡回した(ユニーク)サイト数は324250サイトで、そのうちはてなダイアリーのサイトは49671サイトでした。だいたい1/6くらいなんで、割合として結構多い方であることも確かですね。

Published At2005-03-31 00:00Updated At2005-03-31 00:00

日記
新着ランキングのRSS (17:24)Edit

blogmapの新着ランキングでRSS配信をはじめました。っつーか、ここまだRSS出力作ってなかったのか……。

になります。ちなみに汎用RSS UTF-8化ゲートウェイを通してUTF-8で取得する場合は、

なんて感じになります。UTF-8しか扱えないRSSリーダーを使っている方はこちらをどうぞ。

Published At2005-03-31 00:00Updated At2005-03-31 00:00

日記
blog本のおまけ記事を追加しました (20:48)Edit

RSSを出力するサンプルは書いたけど、RSSを読み込んで利用するサンプルは実用性のないサンプル(単にRSSを読み込んで、各要素が配列に入ったでしょ、で終わり)だったんで、もうちょっと実用的なサンプルをおまけで書いておきました。

Published At2005-03-31 00:00Updated At2005-03-31 00:00

日記
おまけ: RSSをサイドバーに表示Edit

RSSを取得するサンプルについては、XML_RSSを利用したコードを4章3節RSSのところで書いたが、実用的なサンプルではなかったので、ここでもうちょっと実用的なサンプルを補足しておく。

機能としては、blogツールのサイドバーなどにRSSを表示する機能を実装するイメージ。ただしここではサイドバーではなく、index.phpで新着記事一覧を表示した後ろに指定したRSSの内容を表示している。ベースとなるコードは、4章6節で作成したバージョンのHandMadeBlogだ。サンプルアーカイブはソフトバンクパブリッシングのサポートページからダウンロードできる。

他のサイトから取得したRSSを表示する際に、毎回RSSデータをHTTP GETするのは迷惑なので、一度取得したRSSデータは一定期間キャッシュするようにしてある。RSSの表示はテンプレート化されているので、適当に改造して表示するといいだろう。

/config.php

<?php

//キャッシュディレクトリの定義を追加する
define('CACHE_DIR', BLOG_DATA_DIR.'/cache');

?>

上記の設定は、BLOG_DATA_DIRの定義行以降ならばどこに書いてもいい。UNIX系プラットフォームで実行する場合は、上記キャッシュディレクトリにWebサーバーからの書き込み権限を付与しておく必要がある。

/index.php

<?php
/
$Id: index.php 152 2005-03-12 06:00:28Z ishinao $
/

require_once 'config.php';

main();

function
main() {
    
$entry_list = get_recent_entry_list();

    
show_template('htmlheader.tmpl', array(
        
'title' => '新着記事'
    
));
    
show_template('entry_list.tmpl', array(
        
'entry_list' => $entry_list
    
));

    
// $rss_urlで指定したRSSの内容を表示する
    
$rss_url = 'http://1470.net/bm/urlranking.html?mode=rss';
    
show_rss($rss_url, 10);

    
show_template('htmlfooter.tmpl');
}
?>

$rss_urlはコードに直接埋め込んでいるが、設定ファイルなどから取得するようにしておく方が無難だろう。また、複数のRSSを取得し、それらをdc:dateをキーにソートして、最新n件を表示するコードなどを書いてみるのもいいだろう。サイドバーに表示するように改造したい場合は、各要素をテーブルタグで適当に段組して表示するなり、CSSでレイアウトするなりすればいい。

/lib/rsslib.php

<?php

require_once 'XML/RSS.php';

function
show_rss($rss_url)
{
  
$data = parse_rss(get_rss_with_cache($rss_url));
  
show_template('rss_sidebar.tmpl', $data);
}

function
parse_rss($rss_data, $limit = 10)
{
  
$rss =& new XML_RSS();
  
$rss->setInputString($rss_data);
  
$rss->parse();

  if (
preg_match('/charset="(.+?)"/i', $rss_data, $matches)) {
    
$charset = $matches[1];
  } else {
    
$charset = 'auto';
  }

  
$channel = to_euc($rss->getChannelInfo(), $charset);
  
$items = to_euc($rss->getItems(), $charset);
  if (
count($items) > $limit) {$limit = array_slice($items, 0, $limit);}

  return array(
    
'channel' => $channel,
    
'items' => $items,
  );
}

function
get_rss_with_cache($rss_url, $cache_time = 600)
{
  
$cache_file = CACHE_DIR.'/rss_'.urlencode($rss_url);
  if (!
file_exists($cache_file) || filemtime($cache_file) < time() - $cache_time) {
    
touch($cache_file);
    
$rss = file_get_contents($rss_url);
    
$fp = fopen($cache_file, 'w');
    
fwrite($fp, $rss);
    
fclose($fp);
  } else {
    
$rss = file_get_contents($cache_file);
  }
  return
$rss;
}

?>

RSSのパースにはPEARのXML_RSSを使っているので、使える環境を用意する必要がある。また、setInputStringメソッドが使えるXML_Parserにpear upgradeしておく必要がある。具体的なやり方は本書で書いたので省略。

取得したRSSデータの文字コードを内部文字コードであるEUCに変換している。XMLのヘッダ部にcharsetがある場合はそれを見て、なければ(あるいは指定して正規表現にマッチしなければ)autoで文字コード変換をしている。場合によっては、うまく変換できない可能性もある。to_eucはcommon.phpに収録した配列に対応した文字コード変換関数。

URLにはファイル名として使えない文字が含まれる可能性があるため、RSSのURLをURLエンコードしたものをキャッシュファイル名として使用している。この方法だと長いURLだとファイルシステムの文字数制限に引っかかる場合もあるので、md5($rss_url)したファイル名などを使ってもいいだろう。

キャッシュを更新する前にtouchしているのは、RSSをGETするのに長い時間がかかるような場合に、複数のプロセスが同時にRSSをGETしに行くのを防ぐため。ひとまずtouch(キャッシュファイルのmtimeを更新)しておくことで、次のプロセスはひとまず古いキャッシュファイルを読んで動作することになる。

/tmpl/rss_sidebar.tmpl

<h4><a href="<?=h($channel['link']) ?>"><?=h($channel['title']) ?></a></h4>
<dl>
<?php foreach ($items as $item) : ?>
<dt>
<?php if (isset($item['dc:date'])) : ?>
    <?=h($item['dc:date']) ?>
<?php
endif ?>
    <a href="<?=h($item['link']) ?>"><?=h($item['title']) ?></a>
</dt>
<?php if (isset($item['description'])) : ?>
<dd><?=h($item['description']) ?></dd>
<?php endif ?>
<?php
endforeach ?>
</dl>

RSSでは(バージョンにもよるが)URL以外の要素は存在するとは限らないので、もしもあったら表示する、といった形でテンプレートを書いておく。dc:dateはW3CDateフォーマットのまま表示してしまっているが、本当ならばいったんUNIXタイムスタンプなどに変換しておいてから表示した方が融通が利く。特に、dc:dateでソートする場合などにはそのような変換が必須となる。

『自分で作るblogツール(PHP編)』サポートエントリーに戻る

Published At2005-03-31 16:17Updated At2005-03-31 16:17