最近、動画 SEO が にわかに注目を集めています。そう、筆者の中で。
記事に video タグで動画を埋め込んだら、Google 先生の「動画」検索結果に表示させたいですよね。そのためには、動画サイトマップを用意してウェブマスター ツールに登録するのが近道です。でも記事を公開するたびにチマチマ手書きなんて絶対したくないじゃないですか。

となると、動画サイトマップで必須とされている以下の情報を準備して、自動生成するのが解決策になります。
- 動画を掲載したページの URL(loc)
- 動画のタイトル(video:title)
- 動画の説明(video:description)
- サムネイル画像の URL(video:thumbnail_loc)
- 動画ファイルの URL(video:content_loc)または プレイヤーの URL(video:player_loc)
この記事は、Google 先生に読んでいただく動画サイトマップを自動生成するにあたり筆者が実施した手順と、実装として PHP のソースコードを全文掲載しています。積極的に公開するほどのものじゃないです。でも隠すこともない。セルフ ホスティングの動画を video タグで貼り付けたページがあるサイトを前提にしています。YouTube を使うなら もっと簡単かも知れません。それはまた後日。
動画サイトマップとは
まずは目的である動画サイトマップとは何かを把握しておきます。とは いっても、さきほどの Google ウェブマスター ツール ヘルプを見れば一目瞭然。通常の xml サイトマップの形式に、動画向けのメタ情報を追加したものです。
動画サイトマップ(例)
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url>
<loc>(動画を掲載したページの URL *必須)</loc>
<video:video>
<video:thumbnail_loc>(サムネイル画像の URL *必須)</video:thumbnail_loc>
<video:title>動画のタイトル *必須</video:title>
<video:description>動画の説明 *必須</video:description>
<video:content_loc>http://example.com/videos/video.mp4(動画ファイルの URL)</video:content_loc>
<video:player_loc allow_embed="yes" autoplay="ap=1">(動画プレイヤーの URL)</video:player_loc>
<video:duration>動画の長さ(秒で指定) 0~28800(8時間)</video:duration>
<video:rating>動画の評価(0.0~5.0の浮動小数点数で指定)</video:rating>
<video:view_count>動画が再生された回数</video:view_count>
<video:publication_date>2014-09-12T17:01:35+00:00(動画の公開日付 W3C形式)</video:publication_date>
<video:category>動画のカテゴリ(任意)</video:category>
<video:uploader>動画のアップロード者</video:uploader>
<video:live>no(動画がライブ ストリームかどうかを yes / no で指定)</video:live>
</video:video>
</url>
</urlset>
尚、player_loc は、例えば YouTube に動画をアップロードした場合、以下のように指定できます。
... <video:player_loc allow_embed="yes" autoplay="ap=1">http://www.youtube.com/v/jBSFTTZXeAo</video:player_loc> ...
実装の手順と概要
さて、動画サイトマップに必須な情報をどう準備しましょう。
結論から書くと、自分で自分のサイトをスクレイピング(動画のメタ情報を収集)して、それを整形して動画サイトマップ(xml)としてアウトプットするのが一番楽じゃないか、と考えました。
全体の流れは以下になります。
- 各記事ページに動画サイトマップ用のメタ情報を埋め込む
- 自サイトの記事ページ(URL)一覧の取得
- 一覧した記事ページをスクレイピングしてメタ情報を収集
- 収集したメタ情報を xml タグにして動画サイトマップ(xml ファイル)として出力
レールさえ敷ければ大したことない。できればレールの上だけを走りたい。でも時には自分でレールを敷くことも やぶさかではないさ。あ、いきなり脱線しそうになった。レールだけに。くだらないこと書いちゃったけど気にしない。たまには くだらないことも書きたいじゃない。
実装には、WordPress で縁のある PHP を使うことにしました。
各記事ページに動画サイトマップ用のメタ情報を埋め込む
繰り返しになりますが、Google 先生の動画サイトマップに必須の情報は以下です。
- 動画を掲載したページの URL(loc)
- 動画のタイトル(video:title)
- 動画の説明(video:description)
- サムネイル画像の URL(video:thumbnail_loc)
- 動画ファイルの URL(video:content_loc)
動画を掲載したページの URL(loc)
これはつまり、記事ページの URL です。
機械的に取得できそうなので 改めて埋め込む必要はないでしょう。
動画のタイトル(video:title)
動画の説明(video:description)
記事の中で どの部分が動画のタイトルや説明なのか。これは機械的な判断が難しいので、それぞれ「video-title」「video-description」という CSS のクラスを指定することにしました。
例えば以下です。
動画を掲載したページのマークアップ(例)
... <h2 class="video-title">これが動画のタイトルです</h2> <video src="http://example.com/videos/video.mp4" poster="http://example.com/images/video-thumbnail.jpg"></video> <p class="video-description">これが動画のディスクリプションです。</p> ...
サムネイル画像の URL(video:thumbnail_loc)
動画ファイルの URL(video:content_loc)
これらはそれぞれ、video タグの src 属性と poster 属性を取得します。
結果的には、動画のタイトルと動画の説明文に目印(クラス)を付けるだけでよさそうです。
自サイトの記事ページ(URL)一覧の取得
記事ページ(URL)の一覧をどうやって取得しましょうか。そうだ、xml サイトマップって まさしくページ URL の一覧ではないですか! SEO 意識高い系のサイトは絶対に既存でしょう。というわけで、サイトマップから一覧を取得。思ったより簡単でした。詳細は別途 記事にしています。
このあと、記事後半に全文掲載しているソースコードでは 19~ 23行目です。
...
$sitemap = simplexml_load_file( $root . '/post-sitemap.xml' );
$urls = array();
foreach ( $sitemap->url as $url ) {
$urls[] = get_object_vars($url);
}
...
一覧した記事ページをスクレイピングしてメタ情報を収集
サイトマップから取得した URL を順にスクレイピングして動画のメタ情報を収集、あとから整形して出力するために PHP の配列に格納していきます。スクレイピングには、Goutte(グット)というライブラリを使わせていただきました。また、PHP の配列について少し手間取ったのでメモがあります。
このあとのソースコードでは 25~ 60行目です。
収集したメタ情報を xml タグにして動画サイトマップ(xml ファイル)として出力
あとは収集したデータを xml 形式で出力するだけです。ちなみに、一つの記事ページに複数の video タグがある場合にも対応しました。
xml タグの出力は主にソースコード 62~ 88行目です。
最後、ソースコード 90~ 95行目で sitemap-video.xml としてファイルに出力しています。
動画サイトマップ自動生成ツール ソースコード全文(PHP)
<?php
$path = dirname(__FILE__) . '/sitemap-video.xml';
$root = 'http://example.com';
$author = 'Jung Yamaki';
$authorurl = $root . '/about/';
function fArray_merge( $aOld, $aNew ){
foreach($aNew as $sKey=>$mValue){
if ( isset($aOld[$sKey]) && is_array($mValue) && is_array($aOld[$sKey])){
$aOld[$sKey] = fArray_merge($aOld[$sKey], $mValue);
} else {
$aOld[$sKey] = $mValue;
}
}
return($aOld);
}
$sitemap = simplexml_load_file( $root . '/post-sitemap.xml' );
$urls = array();
foreach ( $sitemap->url as $url ) {
$urls[] = get_object_vars($url);
}
require_once 'goutte.phar';
use Goutte\Client;
$client = new Client();
// UserAgent Setting
$client->setHeader('User-Agent', 'dhns Googlebot-Video/1.0');
ob_start(); // buffer output
?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<?php
$i = 0;
$j = 0;
foreach ( $urls as $url ) {
if ( $i++ == 0 ) continue; // skipping top page
$post = $client->request('GET', $url['loc']);
$videos = array();
$videos = $post->filter('video')->each(function( $node ) use ( $root ){
return array(
'thumbnail_loc' => $root . $node->attr('poster'),
'content_loc' => $node->attr('src')
);
});
$vtitle = array();
$vtitle = $post->filter('.video-title')->each(function( $node ){
return array( 'title' => $node->text() );
});
$videos = fArray_merge($videos, $vtitle);
$vdesc = array();
$vdesc = $post->filter('.video-description')->each(function( $node ){
return array( 'description' => $node->text() );
});
$videos = fArray_merge($videos, $vdesc);
?>
<url>
<loc><?php echo $url['loc'] ?></loc>
<?php
foreach ( $videos as $v ){
$j++;
?>
<video:video>
<?php
foreach ( $v as $key=>$val ) {
echo "\t\t\t<video:$key>$val</video:$key>\n";
}
?>
<video:publication_date><?php echo $url['lastmod']; ?></video:publication_date>
<video:family_friendly>yes</video:family_friendly>
<video:category>SEO</video:category>
<video:gallery_loc title="<?php echo $post->filter('title')->text(); ?>"><?php echo $url['loc'] ?></video:gallery_loc>
<video:uploader info="<?php echo $authorurl; ?>"><?php echo $author; ?></video:uploader>
<video:live>no</video:live>
</video:video>
<?php
}
?>
</url>
<?php
}
?>
</urlset>
<?php
$output = ob_get_contents();
ob_end_clean();
$fp = fopen( $path, 'w');
fwrite($fp, $output);
fclose($fp);
補足
出力しておいた方が良さそうだけど、未実装のタグとして、video:tag があります。
- video:tag
-
動画に関連付けるタグです。一般的に、タグは動画やコンテンツに関する簡単な説明を指定するものです。1 つの動画には複数のタグを指定できますが、その動画を登録できるのは 1 つのカテゴリだけです。たとえば、グリル料理に関する動画の場合、「グリル」カテゴリに登録して、「ステーキ」、「肉」、「夏」、「アウトドア」というタグを付けることができます。動画に関連付けるタグごとに <video:tag> 要素を作成します。タグは最大 32 個まで指定できます。
video:tag は、ウェブ ページでいうところの meta keywords に当たるのではないかと筆者は想像しています。Google 先生のページ解析アルゴリズムが進歩した現在、meta keywords は重要視されなくなりましたが、動画解析アルゴリズムは まだ発展途上。いずれ重要視されなくなるとしても、Google 先生に動画コンテンツの中身を伝える意味で、現状では設定しておいた方が良いように感じます。あくまで そんな気がするだけです。
関連記事
もう一度まとめておきます。よろしければご参考にどうぞ。
動画をセルフ ホスティングするにしても、ある程度の規模なら動画 ASP を使うのが一般的かも知れません。ASP なら動画サイトマップの作成ツールなんかも付属するのかも知れませんね。
以前も別の記事で書いたのですが、本稿のような情報は、筆者のように、小規模スタートで ある程度は自分で技術面をカバーし、コスト(リスク)を可能な限り小さくしたい場合に必要なのかなと思います。ヒットする範囲は かなり狭そうですが、どなたかのお役に立てば幸いです。
Pingback: [動画SEO] 動画サイトマップ自動生成の実装を全公開 | Design Hack and Slash | 最新ニュース
Pingback: 【2021年1月アプデ対応】All in One SEOの使い方と一般設定【完全図解マニュアル】 | 情報商材特捜部