RSSフィード表示奮闘記【その2】(ん)

皇紀2678年12月24日

今朝は一段と冷え込みました・・・氷点下2℃(あれ)
玄関先で転んでしまい、Σ(>д<) イテッ!! (かなし)
さて、先日投稿したRSSフィード表示奮闘メモ(ん)の続きです。
かなり長い記事なので、興味のない方はここでUターンを推奨します(@ゆびさし)


先日の記事サンプルでは纏めてRSSを取得して表示する方式でしたが、この方式では一つだけ取得と言う使い方をするにはちょっとした改造が必要でした。
今回はブログなどで組み込んで使いやすいように需要を全く無視したその場で一つのサイトのRSSを取得するバージョンの紹介です(ん)

【使い方】
書式
getrss.php?uri=(フィードのURI)&num=(記事表示数)&disp=(表示形式)&marquee=(数字)&title=(0または1)

getrss.php部分はお好きな名前で(おーけー)その場合にはファイル名を一致させてください(ん)

HP上に展開するには、表示させたい場所に

<iframe src="getrss.php….">~</iframe>

と言う形で使います(ん)

【例】
getrss.php?uri=http://www.pangya.jp/rss/rss.rdf&num=5&disp=0&marquee=0&title=0
パンヤ公式サイトのRSS情報を5個レア形式で取得する。

【使用例】
<iframe src="getrss.php?uri=http://www.pangya.jp/rss/rss.rdf&num=5&disp=0&marquee=0&title=0″></iframe>

【引数内訳】
uri: RSS Feed URI(必須)
num: 記事表示数(任意、既定は5)
disp:表示方法(任意、既定はレア形式)
0=レア形式 <span [id="marquee[1,2,…"]><span><em>(yyyy-mm-dd)</em> <a href="(記事URL)" target="_blank">(記事タイトル)</a></span></span><span>~</span>… のタグを出力する
1=箇条書き形式 <ul [id="marquee[1,2,…"]><li><span>(yyyy-mm-dd)</span><a href="(記事URL)" target="_blank">(記事タイトル)</a></li><li>….</li>….</ul> のタグを出力する
2=テーブル形式 <table [id="marquee[1,2,…"]><tr><th>(yyyy-mm-dd)</th><td><a href="(記事URL)" target="_blank">(記事タイトル)</a></td></tr><tr>…</tr>…</table> のタグを出力する

marquee:(任意、既定は付加しない)
マーキー用の固有 id を 表示形式に従って <span>,<ul>,<table> タグに付加するかを指定
1以上の自然数 = 付加する。"marquee1″,"marquee2″,"marquee3″等とつけられる。
タグ形式にかかわらず付加されます。
0 付加しない

title: (任意、既定は付加しない)
ブログのタイトルを先頭に付けるか
1=付加する (<p class="blogtitle">~</p>) としてRSS記事一覧の前に付加

(ん)っ【パンヤ公式RSSの例】(削除しました)

箇条書き形式は
liScroll – a jQuery News Ticker made easy
と組み合わせることを前提とした出力にしてます(ん)

以下そのスクリプトです(ん)っ

//文字コードは UTF-8,PHPバージョンは5以上(5.2以上を推奨)
//文字化け対策
@mb_language('Japanese');
@mb_internal_encoding('UTF-8');
@date_default_timezone_set("Asia/Tokyo"); # strtotime のタイムゾーン設定(04/23追加)

define("NO_RSS_ADDRESS", "(RSSのアドレスが指定されていません)"); # 既定のメッセージ
define("NO_RSS_CONTENTS", "(RSSを取得できませんでした)");        # 既定のメッセージ
define("NO_RSS_ANALYSIS", "(RSSを解析できませんでした)");        # 既定のメッセージ


# 既定値設定
$dispMode = (isset($_GET["disp"]) && !empty($_GET["disp"])) ? $_GET["disp"] : 0;
$dispNum  = (isset($_GET["num"]) && !empty($_GET["num"])) ? $_GET["num"] : 5;  #既定値は5
$marquee  = (isset($_GET["marquee"]) && !empty($_GET["marquee"])) ? $_GET["marquee"] : 0;  # 既定は0
$dispTitle  = (isset($_GET["title"]) && !empty($_GET["title"])) ? $_GET["title"] : 0;  # 既定は0
# RSS-URIチェック
if(!isset($_GET["uri"]) || empty($_GET["uri"])){
  error(NO_RSS_ADDRESS); exit;
}

# RSS取得
$outdata = "";
$contents = file_get_contents($_GET["uri"]); 
if($contents == false){error(NO_RSS_CONTENTS); exit;}
$rss = simplexml_load_string( $contents, 'SimpleXMLElement', LIBXML_NOCDATA );
if($rss == false){error(NO_RSS_ANALYSIS); exit;}
if(strpos($contents, "<rdf:RDF") === false) {
  if(strpos($contents, '<rss version="2.0"') === false) {
    $isXMLFormat = 0;  # ILLEGAL
  }else{
    $isXMLFormat = 2;  # RFC2822
  }
}else{
  $isXMLFormat = 1;      # W3CDTF
}

if($isXMLFormat == 2){
  # RFC2822
  $outdata .= makeRFC2822TypeRSS($rss, $outdata);
}else if($isXMLFormat == 1){
  # W3CDTF
  $outdata .= makeW3CDTFTypeRSS($rss, $outdata);
}else{
  $outdata .= "<p>更新情報がありません</p>\n";
}

displayRSS($outdata);
exit;
/* メインスクリプトは以上で終了 */
/* RFC2822 タイプのRSSフィード作成 */
function makeRFC2822TypeRSS($rss, $outdata)
{
  global $dispMode,$dispNum,$marquee,$dispTitle;

  $num_of_data = 1;
  $outdata .= ($dispTitle) ? sprintf("<p class=\"blogtitle\">■%s</p>\n", $rss->channel->title) : "\n";
  switch($dispMode){
    case 1:  # <ul><li> 形式
      $outdata .= ($marquee) ? sprintf("<ul id=\"marquee%d\">\n", $marquee) : "<ul>\n";
      foreach ($rss->channel->item as $item) {
        # $link = $item->link;
        $link = str_replace("&", "&amp;", $item->link);
        $title = $item->title;
        # RFC2822 形式の場合には以下の方法で取得
        $date = date("Y-m-d", strtotime($item->pubDate));
        $desc = $item->description;
        $outdata .= sprintf("<li><span>(%s)</span><a href=\"%s\" target=\"_blank\">%s</a></li>\n", $date, $link, $title);
        # dumpValuables($outdata); exit;
        $num_of_data++;
        if($num_of_data > $dispNum){ break; }
      }
      $outdata .= "</ul>\n";
      break;
    case 2:  # <table> 形式
      $outdata .= ($marquee) ? sprintf("<table id=\"marquee%d\">\n", $marquee) : "<table>\n";
      foreach ($rss->channel->item as $item) {
        # $link = $item->link;
        $link = str_replace("&", "&amp;", $item->link);
        $title = $item->title;
        # RFC2822 形式の場合には以下の方法で取得
        $date = date("Y-m-d", strtotime($item->pubDate));
        $desc = $item->description;
        $outdata .= sprintf("<tr><th><span>(%s)</span></th><td><a href=\"%s\" target=\"_blank\">%s</a></td></tr>\n", $date, $link, $title);
        # dumpValuables($outdata); exit;
        $num_of_data++;
        if($num_of_data > $dispNum){ break; }
      }
      $outdata .= "</table>\n";
      break;
    default:  # レア形式
      $outdata .= ($marquee) ? sprintf("<div id=\"marquee%d\">\n", $marquee) : "<div>\n"; # インライン(一行に纏める)形式にする場合には div を span にする
      foreach ($rss->channel->item as $item) {
        # $link = $item->link;
        $link = str_replace("&", "&amp;", $item->link);
        $title = $item->title;
        # RFC2822 形式の場合には以下の方法で取得
        $date = date("Y-m-d", strtotime($item->pubDate));
        $desc = $item->description;
        $outdata .= sprintf("<span><em>(%s)</em><a href=\"%s\" target=\"_blank\">%s</a></span>&nbsp;\n", $date, $link, $title);
        # dumpValuables($outdata); exit;
        $num_of_data++;
        if($num_of_data > $dispNum){ break; }
      }
      $outdata .= "</div>\n"; # インライン(一行に纏める)形式にする場合には div を span にする
      break;
  }
  return $outdata;
}

/* W3CDTF タイプのRSSフィード作成 */
function makeW3CDTFTypeRSS($rss, $outdata)
{
  global $dispMode,$dispNum,$marquee,$dispTitle;

  $num_of_data = 1;
  $outdata .= ($dispTitle) ? sprintf("<p class=\"blogtitle\">■%s</p>\n", $rss->channel->title) : "\n";
  switch($dispMode){
    case 1:  # <ul><li> 形式
      $outdata .= ($marquee) ? sprintf("<ul id=\"marquee%d\">\n", $marquee) : "<ul>\n";
      foreach ($rss->item as $item) {
        # $link = $item->link;
        $link = str_replace("&", "&amp;", $item->link);
        $title = $item->title;
        $dc = $item->children('http://purl.org/dc/elements/1.1/'); # dumpArrays($dc) ;exit;
        preg_match('/^([0-9]{4}\-[0-9]{1,2}\-[0-9]{1,2})[T].+/', $dc->date, $matches);
        $date = $matches[1];
        $desc = $item->description;
        $outdata .= sprintf("<li><span>(%s)</span><a href=\"%s\" target=\"_blank\">%s</a></li>\n", $date, $link, $title);
        # dumpValuables($outdata); exit;
        $num_of_data++;
        if($num_of_data > $dispNum){ break; }
      }
      $outdata .= "</ul>\n";
      break;
    case 2:   # <table> 形式
      $outdata .= ($marquee) ? sprintf("<table id=\"marquee%d\">\n", $marquee) : "<table>\n";
      foreach ($rss->item as $item) {
        # $link = $item->link;
        $link = str_replace("&", "&amp;", $item->link);
        $title = $item->title;
        $dc = $item->children('http://purl.org/dc/elements/1.1/'); # dumpArrays($dc) ;exit;
        preg_match('/^([0-9]{4}\-[0-9]{1,2}\-[0-9]{1,2})[T].+/', $dc->date, $matches);
        $date = $matches[1];
        $desc = $item->description;
        $outdata .= sprintf("<tr><th><span>(%s)</span></th><td><a href=\"%s\" target=\"_blank\">%s</a></td></tr>\n", $date, $link, $title);
        # dumpValuables($outdata); exit;
        $num_of_data++;
        if($num_of_data > $dispNum){ break; }
      }
      $outdata .= "</table>\n";
      break;
    default:   # レア形式
      $outdata .= ($marquee) ? sprintf("<div id=\"marquee%d\">\n", $marquee) : "<div>\n"; # インライン(一行に纏める)形式にする場合には div を span にする
      foreach ($rss->item as $item) {
        # $link = $item->link;
        $link = str_replace("&", "&amp;", $item->link);
        $title = $item->title;
        $dc = $item->children('http://purl.org/dc/elements/1.1/'); # dumpArrays($dc) ;exit;
        preg_match('/^([0-9]{4}\-[0-9]{1,2}\-[0-9]{1,2})[T].+/', $dc->date, $matches);
        $date = $matches[1];
        $desc = $item->description;
        $outdata .= sprintf("<span><em>(%s)</em><a href=\"%s\" target=\"_blank\">%s</a></span>&nbsp;\n", $date, $link, $title);
        # dumpValuables($outdata); exit;
        $num_of_data++;
        if($num_of_data > $dispNum){ break; }
      }
      $outdata .= "</div>\n"; # インライン(一行に纏める)形式にする場合には div を span にする
      break;
  }
  return $outdata;
}
#
# 出力
#
function displayRSS($outdata)
{
header("Content-Type: text/html;charset=utf-8");
echo <<<_EOL_
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>RSSフィード取得サンプル(都度取得版)</title>
<style type="text/css">
  body{font-size: 14px;}
  p{margin-bottom:0.5em;}
  table,ul{margin-bottom:1em;}
</style>
</head>
<body>
{$outdata}
</body>
</html>
_EOL_;
}

/*
    エラー処理
*/
function error($errMsg)
{
  global $dispMode,$dispNum,$marquee,$dispTitle;
  $result = ($dispTitle) ? "<p class=\"blogtitle\">エラー</p>" : "";
  switch($dispMode){
    case 1:  # <ul> 形式
      switch($marquee){
        case 1:  # id を付加する
          $result .= "<ul id=\"marquee1\"><li>" . $errMsg . "</li></ul>\n";
          break;
        default:
          $result .= "<ul><li>" . $errMsg . "</li></ul>\n";
          break;
      }
      break;
    case 2:  # <table> 形式
      switch($marquee){
        case 1:  # id を付加する
          $result .= "<table id=\"marquee1\"><tr><th>&nbsp;</th><td>" . $errMsg . "</td></tr></table>\n";
          break;
        default:
          $result .= "<table><tr><th>&nbsp;</th><td>" . $errMsg . "</td></tr></table>\n";
          break;
      }
      break;
    default:  # レア形式 <span><em>(yyyy-mm-dd)</em>&nbsp;<a href="(記事URL)" target="_blank">(記事タイトル)</a></span>
      switch($marquee){
        case 1:  # id を付加する
          $result .= "<span id=\"marquee1\"><em>&nbsp;</em>" . $errMsg . "</span>\n";
          break;
        default:
          $result .= "<span><em>&nbsp;</em>" . $errMsg . "</span>\n";
          break;
      }
      break;
  }
  displayRSS($result);
  exit;
}


/*
   以下二つの関数はデバッグ用
*/
function dumpArrays($obj){
  header("Content-Type: text/html;charset=utf-8");
  var_dump($obj);
  print "<br />\n";
  print count($obj) . "<br />\n";
  print "<br />\n";
}

function dumpValuables($obj){
  header("Content-Type: text/html;charset=utf-8");
  print $obj;
  print "<br />\n";
  print "<br />\n";
}

 

dumpArrays,dumpValuablesは動作確認用ですので、運用時には削除していただいてかまいません。(あっても動作に支障はありません)
能力のなさが露呈して冗長な部分もありますが,わかりやすさを優先と言うことで(にこ)
お使いのHPに合わせて好きに改造してください。

(まじ)っ 【サニタイズ処理をお忘れなく】

【注】php.ini で allow_url_fopen変数 が Off(または0) の場合、動きません。

ではでは~ε=ε=ε=ε=ε= タタタタ・・・。゜.☆ ドロン♪♪

 【2012-02-03】スクリプト一部修正しました。

 【2013-04-24】スクリプト一部修正しました。

 【2014-06-10】スクリプト一部修正しました。(レア形式表示部分)

HTML(CSS)

Posted by まっちゃん