それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

Googleサイトマップ作成スクリプト

仕事でGoogleSiteMapを作る機会があった。せっかく勉強したのでPHPのクラスにしてみた。

Googleサイトマップ作成は制約通りに作らないとダメ。制約があるのでいくつか処理をする。
Stringに文字列を溜めていくとメモリを使い潰すので、いったんfile php://tempに出力*1していくことにした。

使い方

クラスを初期化し、URL作成をするだけ。

#/usr/bin/php
<?php
require_once "GoogleSiteMap.php";          #クラス初期化

$sitemap = new GoogleSiteMap();
$sitemap->init();                          #出力準備
foreach( range (1,90000) as $idx ){
  $sitemap->add_url_element("/hoge/$idx"); #URLを吐き出し。
}
$sitemap->finish();                        #出力終了

実行結果はこれ

$>php sitemap.php

50000を処理中
render_site_xml:sitemap1.xmlを出力
render_site_xml:sitemap2.xmlを出力
作成したファイルのチェックを開始します
sitemap1.xml:	<URL>50000<filesize>6.37912940979MB
sitemap1.xml:特にエラーは見つかりませんでした。
sitemap2.xml:	<URL>40000<filesize>5.1117973327637MB
sitemap2.xml:特にエラーは見つかりませんでした。

出力と簡単なチェックをする。重複URLもチェックしたいけれどそのうち考える。

Googleサイトマップ作成クラス。

<?php
class GoogleSiteMap{
  public $sitemap_files = 1;
  public $num_of_urls=0;
  public $BASE_URL;
  //sitemapXX.xmlを作成。
  function render_site_xml($buffer) {
    $this->num_of_urls=0;
    $filename = "sitemap".$this->sitemap_files++.".xml";
    file_put_contents( $filename, '<?xml version="1.0" encoding="UTF-8" ?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'.$buffer.'</urlset>');
    file_put_contents("php://stderr","render_site_xml:{$filename}を出力\n");
    return "";
  }
  function add_url_element($url){
    $this->num_of_urls++;
    print '<url>'.
      '<loc>'."{$this->BASE_URL}".$url.'</loc>'.
      '<priority>0.5</priority>'.
      '<changefreq>monthly</changefreq>'.
      '<lastmod>'.date('c').'</lastmod>'.
    '</url>'."\n";
    if($this->num_of_urls>0 && $this->num_of_urls%50000 === 0){
      file_put_contents("php://stderr",$this->num_of_urls."を処理中\n");
      ob_flush();
    }
  }
  function sitemap_index(){
    global $sitemap_files;
    ob_start();
    echo '<?xml version="1.0" encoding="UTF-8"?>'.
      '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
        foreach ( range(1 , $sitemap_files-1)  as $idx ){
          echo '<sitemap>'.
          '<loc>.'.$this->BASE_URL.'/sitemap'. $idx .'.xml</loc>'.
          '</sitemap>';
        }
    echo '</sitemapindex>';
    file_put_contents("sitemap.xml",ob_get_contents() );
    ob_end_clean();
  }
  public function init(){
    ob_start(array( $this,"render_site_xml"), 1024*1024*9.9 );
  }
  public function finish(){
    ob_end_flush();
    //最後にINDEXを書き出す。
    $this->sitemap_index();
    //出力済みをチェックする
    //チェックをする。
    file_put_contents("php://stdout", "作成したファイルのチェックを開始します\n");
    foreach( range(1,$this->sitemap_files-1) as $a ) {
      $filename = "sitemap".$a.".xml";
      $this->check_site_map($filename);
    }
  }
  //チェック関数。
  function check_site_map( $filename ){
    //ファイル読み込む
    $xml = simplexml_load_file($filename);
    file_put_contents("php://stdout", "{$filename}:\t<URL>".sizeof($xml->url)."\t<filesize>".(filesize($filename)/1024/1024)."MB\n");
    //五万件未満
    if( sizeof($xml->url) > 50000 ){
      file_put_contents("php://stdout", "{$filename}:URLの件数超過です\n");
    }
    //サイズチェック
    if( (filesize( $filename ) ) >= (1024 * 1024 *10 )){
      file_put_contents("php://stdout", "{$filename}:URLの件数超過です\n");
    
    }
    //
    file_put_contents("php://stdout", "{$filename}:特にエラーは見つかりませんでした。\n");
  }
}

他にも同じようなもの作ってる人はいるだろうけれど。CodeReposかOpen PEARにでも上げておくかな。

*1:php://stdoutでもTEMP使うみたいなのでstdoutに変更