PHPに惚れました

今でも多分惚れてます。

ニコニコ動画のRSSをPHPで整形

第4回に上げた動画にソース上げて欲しかったとコメントがあったので、ひとつ晒してみます。
稼働中のものを丸っきりそのまま上げている訳ではなく公開用に清書しています。

今動いてるスクリプトよりこっちの方が見やすいです。圧倒的に。
とりあえず以下ソースです。 説明は後ほど。

文字コードUTF-8を前提に記述しています。(UTF-8以外で表示される場合は文字コード変換する関数を各自作ってください。)

ニコニコ動画のRSSをPHPで整形
<?php
function nico_rss($kind="mylist",$cate="all",$day="hourly",$page=0){

	//XMLデータ取得用ベースURL
	$req = "http://www.nicovideo.jp/ranking/".$kind."/".$day."/".$cate."?page=".$page."&rss=2.0";
	$page!=0 ? $page_r=$page*100:$page_r=100;

	//XMLファイルをパースし、オブジェクトを取得
	$xml = simplexml_load_file($req)
	or print("<br>XMLパースエラー。もしくは本家がメンテナンス中です。");

	$rss = array();

	$rss['title'] = $xml->channel->title;
	$rss['link'] = $xml->channel->link;
	$rss['lstBldDate'] = $xml->channel->lastBuildDate;
	$rss['description'] = $xml->channel->description;

	$cnt=0;
	foreach($xml->channel->item as $i){
		foreach($i as $j){
			$ready = preg_replace('/( | ){9,}/',"",$j); //うp主コメ半角を除去
			$ready = preg_replace('/        <p/',"||||||||||<p",$ready);	//
			$ready = split("\|\|\|\|\|\|\|\|\|\|", $ready);	//RSS内のCDATAの3行を分割して配列に格納
			$ready = preg_replace("/<small>|<\/small>/","",$ready); //pタグ内のsmallタグを除去

			foreach($ready as $k){
				$split_status = split("",$k);	//動画ステータスを「|」で3つに分割して配列に格納
			}
		}

		$rss[$cnt]['mov_id']		= preg_replace("/http:\/\/www.nicovideo.jp\/watch\//",NULL,$i->link);    //動画ID
		$rss[$cnt]['rank']			= $cnt+$page_r-99;   //順位
		$rss[$cnt]['points']		= strip_tags($split_status[0]);   //ランキングポイント

		$rss[$cnt]['mov_title']		= $i->title;     //動画タイトル
		$rss[$cnt]['mov_link']		= $i->link;      //動画へのリンク
		$rss[$cnt]['mov_length']		= strip_tags($split_status[1]);   //動画の再生時間
		$rss[$cnt]['mov_status']		= strip_tags($split_status[2],"<strong>,<br>");   //動画ステータス
		$rss[$cnt]['mov_thumbnail']		= strip_tags($ready[1],"<img>");   //サムネイル
		$rss[$cnt]['mov_description']	= strip_tags($ready[2]);    //投稿者説明文

		$cnt++;
	}
	return $rss;
}
print"<pre>";
print_r(nico_rss());
print"</pre>";
?>

処理の流れとしては、
→引数から拾ってくるRSSのURLを指定
XMLファイルをパース、オブジェクトを取得
→整形作業
連想配列に格納
です。

引数はデフォルト値として、「本日の総合マイリストランキング(毎時)1位〜100位」を取得するようになってます。

[$kindに他に使用できる引数]
all・・・すべて
music・・・音楽
ent・・・エンターテイメント
anime・・・アニメ
game・・・ゲーム
animal・・・動物
que・・・アンケート
radio・・・ラジオ
sport・・・スポーツ
politics・・・政治
chat・・・チャット
science・・・科学
history・・・歴史
cooking・・・料理
nature・・・自然
diary・・・日記
dance・・・踊ってみた
sing・・・歌ってみた
play・・・演奏してみた
lecture・・・ニコニコ動画講座
owner・・・投稿者コメント
tw・・・台灣(台湾)
other・・・その他
test・・・テスト
r18・・・R-18


[$dayに他に使用できる引数]
hourly・・・毎時
daily・・・デイリー
weekly・・・週間
monthly・・・月間
total・・・合計


[$cateに他に使用できる引数]
mylist・・・マイリスト登録数
view・・・再生数
res・・・コメント数


[$pageに他に使用できる引数]
1・・・1〜100位
2・・・101〜200位
3・・・201〜300位
$dayによっては最大10まで、1000位まで取得可

では整形作業について説明。

<?php
	$ready = preg_replace('/( | ){9,}/',"",$j); //投稿者説明文の9文字以上続く半角を除去
?>

ここで次の処理の下準備をしています。
まずは9文字以上続く半角、全角スペースを削除。
この処理はあっても無くてもいいかもしれません。過去の名残。
何か表示に異常があればコメントを外してみてください。
現在稼働中のものではコメントアウトはしていません。

<?php
	$ready = preg_replace('/        <p/',"||||||||||<p",$ready);
?>

この処理をしないと投稿者説明文に8文字続く半角スペースがあった時に正しくステータスを分割してくれません。
ここでは半角スペースを|を置換していますが投稿者説明文に記載されなさそうな文字の羅列なら何でも構いません。

<?php
	$ready = split("\|\|\|\|\|\|\|\|\|\|", $ready);	//RSS内のCDATAの3行を分割して配列に格納
?>

先ほど置換した文字列を目印として配列に分割して格納します。
ここで、動画タイトル、サムネイル、動画ステータス群に分割された訳です。

<?php
	$ready = preg_replace("/<small>|<\/small>/","",$ready); //pタグ内のsmallタグを除去
?>

ここは個人の自由に。smallタグを除去しているのは分割したことによって、
smallタグがゴミとして残ってしまったからです。

<?php
foreach($ready as $k){
	$split_status = split("",$k);	//動画ステータスを「|」で3つに分割して配列に格納
}
?>

最後に先ほどの動画ステータス群を「|」でさらに分割します。
再生時間、ランキングポイント、動画ステータスに分割されます。

後は各値を連想配列に格納し抽出しやすくするだけです。
当サイトではこのような方法で整形しています。

rank_oldもRSSの形式は異なりますがやり方は全く同じです。

                                                                                                                                                    • -

ブクマコメに対する返答

    • rank_oldってRSSあったっけ
        • rank_oldはニコニコチャートのRSSを使用しています。CDATAもニコ本家と構成が同じなので扱いやすいですよ。