作成の目的
さまざまな情報サイトではすでに RSS 配信は当然のようになっていますが、ブログツールが普及したために個人サイトでも RSS を発信しているところが多くなり、ウェブサイトの更新状況を把握するための媒体として RSS フィードが標準的なものとして定着してきました。このような状況にあっては、一般論としてブログツールを使っていないサイトでも RSS は提供したほうがよい、と言えると思います。
RSS フィードには RSS 1.0 とか RSS 2.0 とか種類がありますが、どのように記述するかは細かく決まっています。これを手作業で作成するのはちょっとたいへんです。ここのところを補助するため、必要なデータを入力して RSS フィードを作成するツールもあります(窓の杜 RSS 作成支援)。
ただ、個人的にこういったツールがちょっとなじまなかったのは、RSS フィードのための元データはテキストファイルで編集したいし、過去の更新情報も消去するのではなく残しておきたい、という希望があったからです。
そこで慣れないながらも PHP で、データファイルから RSS 1.0 と RSS 2.0 のフィードを生成するスクリプトを書きました。そのうち多少は汎用性があると思われる部分を公開します。
このスクリプトはローカルサーバでブラウザから呼び出して使う想定で書いてありますが、データファイルとスクリプトを(ローカルではない)サーバに置いて実行することも問題ないはずです。
データ形式
UTF-8 のテキストファイルでそれぞれのアイテムを次のように記述。空行がアイテム区切り。マーク行(「-----」)で読み込み終了。マーク行の前には空行を入れない。RSS 生成の対象とならなくなった記事アイテムは、マーク行の後ろに移動する。
link:[tab]記事の URL title:[tab]記事タイトル summary:[tab]記事概要 category:[tab]記事カテゴリ date:[tab]記事公開日時 [空行]
日時は「2009-05-06T22:00:00+09:00」の形式で。最後の「+09:00」はその前の時刻表記が日本時間である、という意味。
スクリプト本体
スクリプト内容は次のとおり。色分けは、PHP の highlight_file 関数によるものです。
<?php
// feed generator script by Kaburaya http://painterfun.com/ 2009/07/01
// このスクリプトは自由にお使いください。ただし作者は動作結果について責任を負いません。
// 参考にしてもらう程度のものとして公開しているので、サポートはありません。
// 入力ファイルを別途作成する必要があります。書式などは付属の feed_generator_readme.txt を参照してください。
// データファイル設定(パス含む)
$update_file = 'updates.dat';
$marker = '-----'; // マーク行
// 出力ファイル名(スクリプトからの相対パス。要書き込み可能属性)
$rss1 = 'index.rdf';
$rss2 = 'index.xml';
// サイト情報(例を参考に変更する)
$site_title = 'Painter Fun!';
$author = 'Kaburaya';
$site_link = 'http://painterfun.com/';
$image = 'http://painterfun.com/open/painterfun_banner.jpg';
$site_description = 'Corel Painter をめぐる雑多な情報提供サイト by Kaburaya';
$about_rss1 = 'http://painterfun.com/index.rdf';
// データファイル読込
$data = fopen($update_file, 'r');
$item_num = 1;
while (!feof($data)) {
$line = fgets($data);
trim($line);
if (!strncmp($marker,$line,5)) {break;} // マーク行があれば終了
if (strlen($line) < 3) { // 空行でアイテム区切り
$item_num++;
continue;
}
$items = explode ("\t",$line);
$key = $items[0];
$value = $items[1];
$entries[$item_num]["$key"] = $value;
}
$update = trim($entries[1]['date:']);
$t = explode('-', (str_replace(array(':','T','+'), '-', $update)));
$timestamp = mktime($t[3],$t[4],$t[5],$t[1],$t[2],$t[0],0);
$update_long = date('D, d M Y H:i:s', $timestamp) . ' +0900';
// 確認用スクリーン出力
print "number of items: $item_num<br />\n";
print "timestamp: $update<br />\n";
var_dump($entries);
print "<br /><br />\n";
//======================================================================
//section 1 : RSS1 RDF
//======================================================================
$file1 = fopen($rss1, 'w');
$string = <<<_RDF_
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns="http://purl.org/rss/1.0/">
<channel rdf:about="$about_rss1">
<title>$site_title</title>
<link>$site_link</link>
<description>$site_description</description>
<dc:language>ja</dc:language>
<dc:date>$update</dc:date>
<image rdf:resource="$image" />
_RDF_;
fwrite($file1, $string);
$string = "<items>\n<rdf:Seq>\n";
for ($count = 1; $count <= $item_num; $count++) {
$link = trim($entries[$count]['date:']);
$string .= "<rdf:li rdf:resource=\"$link\" />\n";
}
$string .= "</rdf:Seq>\n</items>\n</channel>\n\n";
fwrite($file1, $string);
$string = '';
for ($count = 1; $count <= $item_num; $count++) {
$link = trim($entries[$count]['link:']);
$string .= "<item rdf:about=\"$link\">\n";
$title = trim($entries[$count]['title:']);
$string .= "<title>$title</title>\n";
$string .= "<link>$link</link>\n";
$summary = trim($entries[$count]['summary:']);
$string .= "<description>$summary</description>\n";
$category = trim($entries[$count]['category:']);
$string .= "<dc:subject>$category</dc:subject>\n";
$string .= "<dc:creator>$author</dc:creator>\n"; // new
$date = trim($entries[$count]['date:']);
$string .= "<dc:date>$date</dc:date>\n";
$string .= "</item>\n\n";
}
$string .= "</rdf:RDF>\n";
fwrite($file1, $string);
fclose($file1);
//======================================================================
//section 2 : RSS2 XML
//======================================================================
$file2 = fopen($rss2, 'w');
$string = <<<_RSS_
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>$site_title</title>
<link>$site_link</link>
<description>$site_description</description>
<pubDate>$update_long</pubDate>
<language>ja</language>
<image>
<url>$image</url>
<title>$site_title</title>
<link>$site_link</link>
</image>
_RSS_;
fwrite($file2, $string);
$string = '';
for ($count = 1; $count <= $item_num; $count++) {
$string .= "<item>\n";
$title = trim($entries[$count]['title:']);
$string .= "<title>$title</title>\n";
$link = trim($entries[$count]['link:']);
$string .= "<link>$link</link>\n";
$string .= "<guid>$link</guid>\n";
$date = trim($entries[$count]['date:']);
$date = str_replace(array(':','T','+'), '-', $date);
$t = explode('-', $date);
$timestamp = mktime($t[3],$t[4],$t[5],$t[1],$t[2],$t[0],0);
$time = date('D, d M Y H:i:s', $timestamp) . ' +0900';
$string .= "<pubDate>$time</pubDate>\n";
$category = trim($entries[$count]['category:']);
$string .= "<category>$category</category>\n";
$summary = trim($entries[$count]['summary:']);
$string .= "<description>$summary</description>\n";
$string .= "<author>$author</author>\n"; // new
$string .= "</item>\n\n";
}
$string .= "</channel>\n</rss>\n";
fwrite($file2, $string);
fclose($file2);
print "\n<br />\ndone!\n";
?>
このスクリプトとサンプルデータは feed_generator.zip としてまとめましたので、必要でしたらどうぞ。
(2009/07/01)