[PHP] RSSやAtomのフィードを取得してページに表示する方法

By | 2017年8月2日

Webコンテンツを配信するためのXML文書フォーマットであるRSSAtomの情報(フィード)を取得して、自分のサイト内に表示する場合に使うPHPスクリプトについて紹介します。

RSSフィードのアイコン

RSSとAtomでは、XMLの構造が異なるため条件分岐が必要になります。また、同じRSSでも、RSS 2.0RSS 1.0 では書式が異なるため、これらの判定にも条件分岐が必要となります。

今回紹介するPHPスクリプトは、RSS2.0、RSS1.0、Atomの3つを判別して、どのフィードを受け取っても正しく出力できるようにしています。

以下は、北海道大学のRSS「お知らせ/プレスリリース/研究発表」を取得するPHPスクリプトと、取得した情報を表示するHTMLソースです。PHPの関数 simplexml_load_file の引数に、取得したいRSSやAtomのURLを指定します。

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>RSSを取得してページに表示する</title>
</head>

<body>

<?php

	$rss = simplexml_load_file('http://www.hokudai.ac.jp/news/index.xml');

	// Atom であることを表すフラグ
	$isAtom = false;

	// RSS 1.0 であることを表すフラグ
	$isRSS1 = false;

	// RSS 2.0 と仮定して、ひとつのトピックについての情報を取得
	$single = $rss->channel->item;

	if (empty($single)) {
		// 失敗したら Atom とみなして、ひとつのトピックについての情報を取得
		$isAtom = true;
		$single = $rss->entry;
	}

	if (empty($single)) {
		// 失敗したら RSS 1.0 とみなして、ひとつのトピックについての情報を取得
		$isRSS1 = true;
		$single = $rss;
	}

	foreach ($single as $info) {

		// 各投稿の情報を取り出す
		$title = $info->title;

		if ($isRSS1) {
			// RSS 1.0
			$link = $info->link;
			$dc_date = $info->children('http://purl.org/dc/elements/1.1/');
			$date = date('Y/m/d', strtotime($dc_date->date));
			$description = $info->description;
		} else if ($isAtom) {
			// Atom
			$link = $info->link['href'];
			$date = date("Y/m/d", strtotime($info->updated));
			$description = $info->content;
		} else {
			// RSS 2.0
			$link = $info->link;
			$date = date("Y/m/d", strtotime($info->pubDate));
			$description = $info->description;
		}
?>

	<div class="singleRelease">
		<time class="date"><?php echo $date; ?></time> : <a href="<?php echo $link; ?>" target="_blank"><?php echo $title; ?></a>

		<!-- タイトルのみの一覧を表示する場合は下の1行を削除 -->
		<div><?php echo $description; ?></div>
	</div>

<?php
	}
?>
</body>
</html>

ブラウザで表示すると、以下のような結果になります。

プレスリリースのRSSを取得してコンテンツを含めて表示した例

見出しのみを取得した場合は、以下のようになります。

RSSの日時と見出しのみを取得した例

RSSやAtomを取得するスクリプトについて

RSS 2.0 では、RSSのXML構造は以下のようになっています。赤線で囲んでいる部分(itemタグに囲まれた部分)が、ひとつのトピックです。全てのトピックはchannelタグで囲まれています。

RSS2.0におけるXMLの階層構造

したがって、$rss->channel->item はchannelタグの中のitemタグ(ひとつのトピック)を指します。その中に含まれる投稿日時やタイトルなどの情報を取得し、それぞれ適切なタグで表示しています。

この処理を、foreach によってトピックの数だけ繰り返し処理することで、全てのトピックについて取得して表示できます。

RSS2.0 ではなく Atom によるXMLの場合は以下のように、ひとつのトピックを表すタグが item ではなく entry となっています。また、entry の中にある時間や説明、リンク先なども別のタグになっています。

entryタグに囲まれた投稿を含むAtom

(画像は奈良先端科学技術大学院大学のプレスリリースのAtom)

RSS 1.0 の場合は、最も外側を囲むタグ rdf:RDF の直下に、直接個々のトピックを表す item が存在する構造になっています。

RSS1.0のXML構造

(画像は科学技術振興機構のプレスリリースのRSS1.0)

対象となるXMLがAtomであった場合、$rss->channel->item は定義されないため、RSS 2.0 としての情報の取得が失敗し、以下のif文が実行されます。

...
	if (empty($single)) {
		// 失敗したら Atom とみなして、ひとつのトピックについての情報を取得
		$isAtom = true;
		$single = $rss->entry;
	}
...

$isAtom が true であれば対象のXMLがAtomであると判断し、それに応じて後に取得するタグを変更します。Atom としての取得が失敗した場合は RSS 1.0 とみなして、以下のif文を実行します。

...
	if (empty($single)) {
		// 失敗したら RSS 1.0 とみなして、ひとつのトピックについての情報を取得
		$isRSS1 = true;
		$single = $rss;
	}
...

その後、条件に合うデータタグの取得を試みます。

...
	if ($isRSS1) {
		// RSS 1.0
		$link = $info->link;
		$dc_date = $info->children('http://purl.org/dc/elements/1.1/');
		$date = date('Y/m/d', strtotime($dc_date->date));
	} else if ($isAtom) {
		// Atomの場合
		$link = $info->link['href'];
		$date = date("Y/m/d", strtotime($info->updated));
		$description = $info->content;
	} else {
		// RSS 2.0
		$link = $info->link;
		$date = date("Y/m/d", strtotime($info->pubDate));
		$description = $info->description;
	}
...

以下は、奈良先端科学技術大学院大学のプレスリリースのAtomから時間とタイトルのみを取得した例です。RSS 2.0 と同じように取得できます。

奈良先端科学技術大学院大学のプレスリリースのAtomをPHPで取得した例

以上、PHPでRSSやAtomの情報を取得してページに表示する方法でした。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です