XMLの定義(規格):名前空間
YouTubeの各チャンネルの新着情報をゲットするには、
https://www.youtube.com/feeds/videos.xml?channel_id='channelid'
で取得出来ます。
channelidは、各自好きなチャンネルIDに変更して下さい。
ブラウザーのアドレスに入力して開いて見て下さい。先頭の行に以下のように書かれています。
<feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" xmlns:media="http://search.yahoo.com/mrss/" xmlns="http://www.w3.org/2005/Atom">
これは、このXMLファイルの規格が3つ有る事を示しています。
「w3」がベースの規格を作っていて「yahoo」「youtube」の拡張規格を一部使っていると言う事になります。
「yt」「media」を名前空間(namespace)と呼びます。
XMLをもう少し見てみると以下のようなタグが有ります。
<yt:channelId>
これは、「xmlns:yt」で定義された「channelId」タグと言う事です。
PHPでXMLファイルを扱う
PHPでXMLファイルを扱う場合は、「simplexml_load_string」や「simplexml_load_file」を使うのが一般的みたいです。
しかし、simplexmlを使う場合に名前空間が無視されてしまうので
一手間必要になってくるのですが、「PHP+XML」でググっても必要な情報が手に入らないので「PHP+XML+名前空間」でググってみて下さい。
今回は、「YouTubeの新着情報RSS(XML)」を解析するPHPプログラムで「file_get_contents + new SimpleXMLElement」を使う方法と「new DOMDocument」を使う方法をご紹介致します。
new SimpleXMLElementを使う方法
$ns = $sxe->entry->getNamespaces(true);
$media = $ent->children($ns[‘media’]);
2行と
$media = $ent->children(‘media’,true);
は、同じで第2引数を「true」にする事で名前空間名で指定出来ます。「children」を使う事で、名前空間にアクセス出来ます。
<?php $channel_id = 'UCrXUsMBcfTVqwAS7DKg9C0Q'; $url = 'https://www.youtube.com/feeds/videos.xml?channel_id=' . $channel_id; $xml = file_get_contents($url); $sxe = new SimpleXMLElement($xml, LIBXML_NOCDATA); // $sxe = simplexml_load_file($url); $sid = str_replace("yt:channel:", "", $sxe->id); echo $sid . "<br />"; echo $sxe->title . "<br />"; echo $sxe->link[1]->attributes()->href . "<br />"; echo $sxe->published . "<br /><br />"; foreach ($sxe->entry as $ent) { $oid = str_replace("yt:video:", "", $ent->id); echo $oid . "<br />"; echo $ent->title . "<br />"; echo $ent->link->attributes()->href . "<br />"; echo $ent->published . "<br />"; echo $ent->updated . "<br />"; //$ns = $sxe->entry->getNamespaces(true); //$media = $ent->children($ns['media']); $media = $ent->children('media',true); $gp = $media->group; echo $gp->thumbnail->attributes()->url . "<br />"; echo "<pre>"; echo $gp->description; echo "</pre>"; foreach($gp->community->starRating->attributes() as $att) { echo $att . "<br />"; } echo $gp->community->statistics->attributes()->views . "<br /><br />"; }
DOMDocumentを使う方法
getd($tag, $num=0)関数と
gete( $tag)関数を定義しています。
「getElementsByTagName」が長すぎるので呼び出しが楽になりプログラムがすっきりするようにしています。
DOMDocumentを使う場合は名前空間を気にしないでタグを拾うことが出来ます。(名前空間を指定する事も出来ます。)
「getElementsById」を使う事でピンポイントで取得可能なので「id」が指定されている場合はDOMDocumentを使うと楽になります。
<?php $st = microtime(true); $channel_id = 'UCrXUsMBcfTVqwAS7DKg9C0Q'; $url = 'https://www.youtube.com/feeds/videos.xml?channel_id=' . $channel_id; $dom = new DOMDocument('1.0', 'UTF-8'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $dom->load($url); $ent = null; function getd($tag, $num = 0){ global $dom; return $dom->getElementsByTagName($tag)[$num]; } function gete($tag){ global $ent; if($ent == null)return; return $ent->getElementsByTagName($tag)[0]; } echo getd('channelId')->nodeValue . '<br />'; echo getd('title')->nodeValue . '<br />'; echo getd('link', 1)->getAttribute("href") . '<br />'; echo getd('published')->nodeValue . '<br /><br />'; $entry = $dom->getElementsByTagName('entry'); foreach ($entry as $ent) { echo gete('videoId')->nodeValue . '<br />'; echo gete('title')->nodeValue . '<br />'; echo gete('link')->getAttribute("href") . '<br />'; echo gete('published')->nodeValue . '<br />'; echo gete('updated')->nodeValue . '<br />'; echo gete('thumbnail')->getAttribute("url") . '<br />'; echo "<pre>"; echo gete('description')->nodeValue . '<br />'; echo "</pre>"; $starRating = gete('starRating'); echo $starRating->getAttribute("count") . '<br />'; echo $starRating->getAttribute("average") . '<br />'; echo $starRating->getAttribute("min") . '<br />'; echo $starRating->getAttribute("max") . '<br />'; echo gete('statistics')->getAttribute("views") . '<br /><br />'; } $end = microtime(true); echo '処理時間:'.($end - $st)."秒<br />";