ブログの更新情報をRSSから取り出す

 ある複数のブログの更新状態をブログとは別の HTML ページでまとめて表示したい(例えば、ある企業のブログの更新状況を、その企業のサイトのトップページに自動で表示したいといった場合)。欲しいのは、エントリーのタイトルと日付とサマリー。

 というようなとき、最も手っ取り早いのは、ブログが吐き出す RSS を利用することだろう。でも XML を扱うのってちょっと面倒くさい。パースだのハンドラーだの、なんじゃそれは? いやちょっと待ってくれ、欲しい情報はほんのわずかなんだ。最新のエントリーひとつ分の上記の内容だけ。

 だったら、単純に文字列として取り込んで、必要なものだけ抜き出した方が早くないか? 使用する RSS のタイプも最初から決めてしまえば、RSS のバージョンに振り回される必要もない。別に汎用のリーダを作ろうってわけじゃないんだから。

 というわけで、文字コード UTF-8、データ形式は Atom、日付は降順になっていることを前提に、やってみた。以下がそのコード。

<?php

// Get Entry Value of RSS Feed
function getEntVal ($URL) {
  // 保存/読込用のファイル名を準備
  $Path = pathinfo($URL);
  $DirName = $Path["dirname"];
  $DirName = str_replace('http://XXXXX.weblogs.jp/', '', $DirName);
  $FileName = $Path["basename"];
  $NewFileName = $DirName . '_' . $FileName;
  $NewPath = './rss/' . $NewFileName;

  $RemoteFile = fopen($URL, 'r');
  $FirstLine = fgets($RemoteFile); // 先頭の1行を読込

  $EntTitle = '';
  $EntDate = '';
  $EntSummary = '';
  $Flag = 0;

  // 読み込んだファイルが正しいか確認
  // OK の場合、1行ずつ配列に読み込み、条件が揃ったら終了し、ファイルに保存
  // 注)最初の設置時点では正規ファイルを自分でコピーしておくこと
  if (strpos($FirstLine, '<?xml ') !== FALSE) {
    $ForCopy = '';
    for ($i = 0; $LVal = fgets($RemoteFile); $i ++) {
      // entory 開始タグに当たるまではスルー
      if (strpos($LVal, '<entry>') !== FALSE) {
        for ($j = 0; $LVal2 = fgets($RemoteFile); $j ++) {
          $LVal2 = trim($LVal2);
          if (strpos($LVal2, '<title>') !== FALSE)     { $EntTitle   = strip_tags($LVal2); }
          if (strpos($LVal2, '<published>') !== FALSE) { $EntDate    = strip_tags($LVal2); }
          if (strpos($LVal2, '<summary>') !== FALSE)   { $EntSummary = strip_tags($LVal2); }
          $ForCopy .= $LVal2 . "\n";
          // 変数が3つとも埋まるか、entry が閉じられたら終了
          if (
            ($EntTitle != '' && $EntDate != '' && $EntSummary != '')
             || (strpos($LVal2, '</entry>') !== FALSE)
          ) {
            $Flag = 1;
            break;
          }
        }
        break; // 処理完了、ループを抜ける
      }
    }
    // 文字列をファイルに保存
    //file_put_contents($NewPath, $ForCopy);
    $CopyFile = fopen($NewPath, 'w');
    fwrite($CopyFile, $ForCopy);
    fclose($CopyFile);

  // NG の場合、既存のファイルを読込んで処理
  } else {
    if (file_exists($NewPath)) {
      $LineAry = file($NewPath);
      foreach ($LineAry as $LVal2) {
        $LVal2 = trim($LVal2);
        if (strpos($LVal2, '<title>') !== FALSE)     { $EntTitle   = strip_tags($LVal2); }
        if (strpos($LVal2, '<published>') !== FALSE) { $EntDate    = strip_tags($LVal2); }
        if (strpos($LVal2, '<summary>') !== FALSE)   { $EntSummary = strip_tags($LVal2); }
        // 変数が3つとも埋まるか、entry が閉じられたら終了
        if (
          ($EntTitle != '' && $EntDate != '' && $EntSummary != '')
           || (strpos($LVal2, '</entry>') !== FALSE)
        ) {
          $Flag = 1;
          break;
        }
      }
    }
  }

  if ($Flag) {
    // 日時の整形
    $EntDate = trim($EntDate, '+09:00');
    $EntDate = str_replace('T', ' ', $EntDate);
    $EntDate = date('Y年m月d日 H:i', strtotime($EntDate));

    $Return['Title'] = $EntTitle;
    $Return['Date'] = $EntDate;
    $Return['Summary'] = $EntSummary;

    return $Return;
  } else {
    return FALSE;
  }
}

$NewEnt = getEntVal('http://XXXXX.weblogs.jp/DDDDD/atom.xml');
var_dump($NewEnt);

?>

 日時の整形をちょこちょことやっているのは、例にした TypePad の Atom の出力が 2008-02-17T15:14:22+09:00 というような形式だったからだが、こころへんは読み込む RSS によっては違うのかもしれないので、その場合は適宜改良が必要。もっとも、関数内にしたって用途に応じて改良は必要になるだろう。しかし短いスクリプトだから変更も容易なはずだ。

(2008.2.24追記)

 上記コード修正。リモートのファイルは file 関数で読み込むより fopen で読み込んだ方が、表示が早くなるようだ。また、保存ファイルも、必要な情報のみ抜きだして保存するよう変更した。

もっと簡単な方法

 TypePad限定なら、もっと簡単な方法がある。上級者テンプレートで、フォーマット済みのインデックスファイルを新規に作成し、Webページ側からはそのファイルをただ読込んで表示すればよい。別にフィードを解析する必要はない。TypePadの扱いに慣れてきて、ようやく思いついた方法。
 MovableTypeでも同様のことは可能だろうし、他のブログやCMS系でも、テンプレートを追加自作できるものなら、このアイディアで応用できる筈だ。
 この方法だと、上記コードの大部分(読込み後)の処理が不要になる。orz
 結局、自分が管理していないサイトのフィードを取得しなければならない場合に限って、上記コードが応用できる。(そういう状況って、あまりないよね、きっと)

Tail-Lagoon @ 19:51

コメントおよびトラックバック受付中です。
TB : http://weblogs.tail-lagoon.com/WebPC/2008/02/17/8/trackback/

コメントをどうぞ

この投稿へのコメントは RSS 2.0 フィードで購読できます。