【php】ブログとFacebookからRSSを取得してサイトに表示

久しぶりの更新です。
WEBサイトの「更新情報」の欄に
ブログ(Livedoorブログ)とFacebookどちらも更新情報を載せたい。
という要望を頂きました。

キーワードとしては、
php5、simplexml_load_file、FacbookのRSS、LivedoorブログのRSS
当たりかと思います。
環境・参考ページは下にまとめてます。



概要、プログラムの作り

今回はDBを使わずにRSSの情報を整形するというやり方をしました。
必要な情報は、
「更新日」、「タイトル」、「リンク先」、「ブログorFacebook」の4つだけです。

流れとしては、
・ブログのRSSから各情報を取得

・オブジェクトに格納

・FacebookのRSSから各情報を取得

・同じオブジェクトに追加格納

・投稿日時順で並べ替え

・最新の5つをHTMLで表示
となります。

では、制作開始。

LivedoorブログのRSSから情報を取得、格納

使うのは、simplexml_load_fileです。
構文はこんな感じ。
SimpleXMLElement simplexml_load_file ( string $filename [, string $class_name = "SimpleXMLElement" [, int $options = 0 [, string $ns = "" [, bool $is_prefix = false ]]]] )
指定したファイルの中の整形式 XML ドキュメントをオブジェクトに変換します。
出典:PHP: simplexml_load_file - Manual

こんな感じに作りました。
//ブログフィード
$url = 'http://******.blog.jp/index.rdf';
$xml = simplexml_load_file($url);
$i = 0;
foreach ($xml->item as $item) {
$blog = array();
$blog['type'] = 'ブログ更新';
$blog['link'] = (string)$item->link;
$title = (string)$item->title;
$blog['title'] = $blog['type'] . ' | ' . mb_strimwidth($title, 0, 70, '...');
$date = $item->children('http://purl.org/dc/elements/1.1/')->date;
$blog['date'] = date('YmdHi', strtotime($date));
$data[] = $blog;
$i++;
if ($i > 4){break;}
}

LivedoorブログのRSSを取得

ソースからURLを取得。
<link rel="alternate" type="application/rss+xml" title="RSS" の部分から。
http://******.blog.jp/index.rdf
RSSは1.0です。

オブジェクトに格納

RSSから関数simplexml_load_fileで情報を取ってきて、
必要情報のみforeachで格納していきます。

「ブログorFacebook」を識別する用に$blog['type']を作りました。
HTMLにも表示される文言です。
$blog['type'] = 'ブログ更新';

タイトルは文字数制限を70文字にかけています。
$title = (string)$item->title;
$blog['title'] = $blog['type'] . ' | ' . mb_strimwidth($title, 0, 70, '...');

日時はRSSの中で「dc:」が入っているデータのため、そのままでは格納できません。
RSSのソースの上の方に「dc:」の参照元があります。
<rdf:RDF ~中略~ xmlns:dc="http://purl.org/dc/elements/1.1/" ~中略~>
ここを通して取得するようです。
$date = $item->children('http://purl.org/dc/elements/1.1/')->date;
参考:【php】SimpleXMLでRSSを取得する
RDFや「dc:(名前空間接頭辞)」についてはRDF -- リソース表現のフレームワークを参照。

続いて、Facebookです。

FacebookのRSSから情報を取得、追加格納

こちらも使うのは同じくsimplexml_load_fileです。
//facebookフィード
ini_set('user_agent',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3');
$fbstr=file_get_contents('https://www.facebook.com/feeds/page.php?id=***************&format=rss20');
$fbxml = simplexml_load_string($fbstr, 'SimpleXMLElement', LIBXML_NOCDATA);
$i = 0;
foreach ($fbxml->channel->item as $item) {
$fb = array();
$fb['type'] = 'facebook更新';
$fb['link'] = (string)$item->link;
$title = (string)$item->title;
$title = html_entity_decode($title);
$title = mb_convert_encoding($title, 'UTF-8', 'HTML-ENTITIES');
$title = str_replace(array("\r\n", "\r", "\n"), '', $title);
$fb['title'] = $fb['type'] . ' | ' . mb_strimwidth($title, 0, 55, '...', 'UTF-8');
$fb['date'] = date ( 'YmdHi',strtotime ( $item->pubDate ) );
$data[] = $fb;
$i++;
if ($i > 4){break;}
}

FacebookのRSSを取得

FacebookはIDが分かればRSSのURLが分かります。
IDの確認方法は、
FacebookのユーザーIDを簡単に確認する方法を参照。

IDが分かれば******の部分をID番号にしたURLがRSSです。
https://www.facebook.com/feeds/page.php?id=***************&format=rss20

user_agentを指定して情報を取得

Facebookはプログラムの関数によるアクセスができない様にになっているため、
user_agentをブラウザということにして情報を取得します。
ini_set('user_agent',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3');
$fbstr=file_get_contents('https://www.facebook.com/feeds/page.php?id=***************&format=rss20');
参考は、Facebookページの書き込みをRSSで取得してPHPで処理する

同じオブジェクトに追加で格納

ここからはブログとほぼ同じです。
simplexml_load_fileで情報取得、foreachで格納。

「ブログorFacebook」識別は$fb['type']です。

文字参照を変換
RSSに入っている「タイトル」情報がそのままでは文字参照(&#x3053;など)となっています。
関数mb_convert_encodingで変換します。

その後、html_entity_decodeでHTMLタグを削除(デコード)、
関数str_replaceで改行などを削除します。
最後に文字数制限して格納します。
参考は、数値文字参照と日本語文字列の相互変換をする【PHP】
$title = (string)$item->title;
$title = mb_convert_encoding($title, 'UTF-8', 'HTML-ENTITIES');
$title = html_entity_decode($title);
$title = str_replace(array("\r\n", "\r", "\n"), '', $title);
$fb['title'] = $fb['type'] . ' | ' . mb_strimwidth($title, 0, 55, '...', 'UTF-8');

HTMLに記述する際に、別々で表示するなら別のオブジェクトに格納した方がいいのですが、
今回要望として「同じ更新情報欄で表示したい」というのがありました。
なので、同じ$data[]の配列に追加で格納します。
$data[] = $fb;

投稿日時順で並べ替え

$data[]に格納したブログ、Facebookそれぞれの情報を投稿日時順(降順)で並べ替えます。
今回はPHPで、オブジェクトの配列をソートする。を参考に、関数usortを使いました。
$sdata = usort( $data , 'cmp_date_type' );

function cmp_date_type( $a , $b){
$cmp = strcmp( $a['date'] , $b['date'] );
if( $cmp == 0 ){
$cmp = strcmp( $a['type'] , $b['type'] );
}elseif( $cmp < 0){
return 1;
}elseif( $cmp > 0){
return -1;
}
}
functionでソート条件を設定して、usortでソートする形です。
今回は降順なので、$aと$bを比べた結果($cmp)を逆転させています。
たぶんもっとすっきりした記述があると思います…

HTMLに記述

データは出来上がったので、後はHTMLに記述していくだけです。
ここは簡単。
for ( $i = 0; $i <= 4; $i++ ) {
echo '<dt>' . date('Y年n月j日',strtotime($data[$i]['date'])) . "</dt>\n" .
'<dd><a href="' . $data[$i]['link'] . '" target="_blank">' .
$data[$i]['title'] . "</a></dd>\n";
}
5つしかないのでforで回しました。
ソートの為にYmdHi(201407291750)の形で整形してましたが、
表示は日付だけなのでここで再整形。

表示結果はこんな感じになります。
<dt>2014年7月29日</dt>
<dd><a href="http://www.facebook.com/****/posts/***************" target="_blank">facebook更新 |  こんにちは。~...</a></dd>
<dt>2014年7月29日</dt>
<dd><a href="http://******.blog.jp/archives/********.html" target="_blank">ブログ更新 | 夏の~</a></dd>
<dt>2014年7月28日</dt>
<dd><a href="http://www.facebook.com/****/posts/***************" target="_blank">facebook更新 |  こんばんは、~...</a></dd>
<dt>2014年7月28日</dt>
<dd><a href="http://******.blog.jp/archives/********.html" target="_blank">ブログ更新 | 本日~</a></dd>
<dt>2014年7月27日</dt>
<dd><a href="http://******.blog.jp/archives/********.html" target="_blank">ブログ更新 | 冷たい~</a></dd>
というわけで今回は、
LivedoorブログとFacebookの更新情報をサイトに表示する
を実装しました。

===========================
環境
Windows7
レンタルサーバ
php5
HTML5&CSS3
===========================

その他参考-------------
simplexml_load_file()でRSS1.0(dc:dateなど)を扱う
Facebook 投稿ごと単独のURL

web-product

TOPへ戻る

TOP