XML_Feed_Parserで簡易フィードリーダー(RSSリーダー)を作る

フィードリーダー(RSSリーダー)のPHPスクリプトを書いてみました。機能は以下の通りです。

  • フィードのタイトル、記事のタイトル、記事の作成日時、要約(もしくは、本文の始めの部分)を表示する
  • RSS1.0、同2.0、Atom1.0に対応
  • 新しいものから順に表示する


XMLを読み込む等の処理にはフィードパーサと呼ばれる、XMLの構造を解析してくれるプログラムを使うと便利です。今回はPEARのライブラリの一つである、XML_Feed_Parserを使ってみました。

以下のスクリプトでの重要な部分は、対象となるフィードに含まれた記事をすべて配列に取り込んでから、記事の作成日時でソート(並び替え)する部分です。フィードの形式によって日時の表示形式は異なっているので、異なる形式のフィードが混じっていると、日時で正しく並び替えることはできないのですが、XML_Feed_Parserはフィードに記載されている日時をすべてタイムスタンプ(1970年1月1日0時0分0秒からの経過秒数)に変換してくれます。そのおかげで、タイムスタンプを使って記事を正しく並び替えられるようになります。

<?php
$feeds = array(
              "http://hogehoge.com/index.rdf",
              "http://fugafuga.net/atom.xml",
             );
//-------------------------------------
require_once 'XML/Feed/Parser.php';

$entries = array(); //記事を1件ごとに格納する配列

foreach ($feeds as $url) {
  //フィードの読み込み
  $source = file_get_contents($url);
  try{
    $feed = new XML_Feed_Parser($source,false,true);
  } catch (XML_Feed_Parser_Exception $e) {
    die("Invalid Feed : $url". $e->getMessage());
  }

  $feed_title = $feed->title;   //各フィードのタイトル

  foreach ($feed as $entry) {
    //フィードのフォーマットによって処理を変える
    if ($feed->version() == "RSS 1.0") {
      $timestamp = $entry->date;
      $description = $entry->description;
      }
    if ($feed->version() == "RSS 2.0") {
      $timestamp = $entry->pubDate;
      $description = $entry->description;
    }
    if ($feed->version() == "Atom 1.0") {
      $timestamp = $entry->published;
      $description = $entry->summary;
    }
    //記事の内容を配列に格納
    $entries[] = array(
                    "feed_title"     => $feed_title,
                    "entry_title" => $entry->title,
                    "link"     => $entry->link,
                    "timestamp" => $timestamp,
                    "description" => $description,
                    );
  }
}
//並べ替え
uasort($entries,"cmp_desc");

//並べ替え用の比較関数
function cmp_desc($a, $b) {
  if($a['timestamp'] >= $b['timestamp']) return -1;
  if($a['timestamp'] == $b['timestamp']) return 0;
  if($a['timestamp'] <= $b['timestamp']) return 1;
}
?>
<html>
<head><title>RSS Reader</title></head>
<body>
<ul>
<?php
//表示する
foreach ($entries as $entry) {
  if (preg_match('/^(https?)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)$/',$entry['link'])) {
  echo '<li>';
  echo '<a href="' . $entry['link'] . '">';
  echo htmlspecialchars($entry['entry_title'],ENT_QUOTES);
  echo '</a>';
  echo ' ' . strftime("%Y-%m-%d %H:%M",$entry['timestamp']);   //タイムスタンプを分かりやすい形式に変換
  echo ' (' . htmlspecialchars($entry['feed_title'],ENT_QUOTES) . ')';
  echo ' <br>' . mb_substr(strip_tags($entry['description']), 0, 120, 'UTF-8');   //要約は120字まで表示する
  echo '</li>';
  }
}
?>
</ul>
</body>
</html>