Perl > XML::TreePPでXMLサイトマップファイルを生成
perlで動く軽めのXMLパーサとしてXML::TreePPがある。これを用いてXMLのサイトマップを生成するcgiを作ってみよう。XMLパーサを使ってXMLサイトマップを作るなんてのは何番煎じになるのかわからないけれど、XML::TreePPを使ってサイズの大きくならないXMLファイルの生成について記事を書こうと思ったらこうなった。
cgiファイルのソース
#!/usr/local/bin/perl -wT
use strict;
use warnings;
use DateTime;
use DateTime::Format::W3CDTF;
use XML::TreePP;
my @target = &set_target();
&make_sitemap(@target);
exit;
sub set_target
{
opendir DIR, "./";
my @target = grep{m/^\w+\.html$/} readdir DIR;
closedir DIR;
return @target;
}
sub set_priority
{
my $mtime = shift;
return sprintf("%2.1f", $_ eq 'index.html' ? 1.0 : 0.5);
}
sub set_lastmod
{
my $mtime = shift;
my $dt = DateTime->from_epoch( time_zone => 'Asia/Tokyo', epoch => $mtime );
return DateTime::Format::W3CDTF->format_datetime($dt);
}
sub set_changefreq
{
my $mtime = shift;
my $changefreq = '';
my $sub = time - $mtime;
my $diff = 60;
if ($sub < $diff ) {
$changefreq = 'always';
} elsif ($sub < ($diff *= 60)) {
$changefreq = 'hourly';
} elsif ($sub < ($diff *= 24)) {
$changefreq = 'daily';
} elsif ($sub < ($diff *= 7)) {
$changefreq = 'weekly';
} elsif ($sub < ($diff *= 30)) {
$changefreq = 'monthly';
} elsif ($sub < ($diff *= 12)) {
$changefreq = 'yearly';
} else {
$changefreq = 'never';
}
return $changefreq;
}
sub set_url
{
my $file = shift;
my $mtime = (stat($file))[9];
my $url = {
changefreq => &set_changefreq($mtime),
lastmod => &set_lastmod($mtime),
loc => $file,
priority => &set_priority($mtime),
};
return $url;
}
sub make_sitemap
{
my $tpp = XML::TreePP->new();
my $tree = {
'urlset' => {
'-xmlns' => 'http://www.google.com/schemas/sitemap/0.84',
url => [
],
},
};
@{$tree->{urlset}->{url}} = map{&set_url($_)}@_;
$tpp->writefile("./sitemap.xml", $tree);
return;
}
__END__
set_target
サイトマップを生成したいファイルの配列を返す。
make_sitemap
ファイルが書かれた配列引数を受け取って、それぞれのファイルについてurlタグの内容を生成するサブルーチンを呼び出す。生成されたハッシュをTreePPのwritefileでXMLに変換して書き込み
- sitemap.xml - Google 検索
- Google ウェブマスター ツール
- treepp writefile - Google 検索
- [Perl] XML::TreePP - Pure Perl実装によるXMLファイル展開モジュール
set_url
サイトマップを生成したいファイルを引数としてurlタグと対応した連想配列を返す。更新時間を元にurlタグの内容(loc, lastmod, changefreq, priorityタグ)を生成する。
set_priority
ファイルの最終更新時間を引数として、priorityタグの内容を返す。このスクリプトでは最終更新時間を受け取っているがそれに関連した処理は行っていない。単純にindex.htmlはゲートページなのでこのプライオリティを1.0としてそれ以外は0.5にしている。もっと複雑なルールが必要ならばこのサブルーチンの中に書く。
set_lastmod
ファイルの最終更新時刻を引数として、lastmodタグの内容を返す。DataTimeと出力フォーマットのDateTime::Format::W3CDTFを使って、ファイルの最終更新時刻を適当な時刻フォーマット(W3C Datetime)に変換しているだけ。W3C DatetimeはISO8601で定義されているのでDateTime::Format::ISO8601を使うのが正攻法だが、このサブセットであるW3CDTFのほうが単純なのでDateTime::Format::W3CDTFを使っている。
- W3C Datetime - Google 検索
- Date and Time Formats
- Modules - Perl DateTime Wiki
- perl datetime - Google 検索
- DateTime - A date and time object - search.cpan.org
- DateTime::Format::W3CDTF - Parse and format W3CDTF datetime strings - search.cpan.org
- DateTime::Format::ISO8601 - Parses ISO8601 formats - search.cpan.org
- 日付の表記に関するノート
- DateTime - モダンなPerl入門 - モダンなPerl入門
- Perlにおける各種日付フォーマットの変換と比較 - 発声練習
set_changefreq
ファイルの最終更新時刻を引数として、changefreqタグの内容を返す。ファイルの最終更新時刻を元に、cgiが呼び出された時刻と比較して60秒以内に更新があったらalways、60*60秒以内なら'hourly'等の文字列を返す。更新頻度というよりも更新したタイミングからどのくらい経過したかという意味になっているのであまりよろしくないと思うけれど。
[perl] 1 行スクリプト覚書 with Active Perl
ここでは perl の 1 行スクリプトを使用し、単一の機能をどれだけ短いスクリプトで表現できるかを模索していきます。Windows のコマンドラインが非力なのは仕方ありません。GUI が売り物の Windows ですから。unix ほどの高機能なシェルはいらないけど、unix 使いに負けないくらいの仕事がしたい貴方に。単一の機能の集合がプログラムで、短い行で様々な機能を実現できればプログラムを書くのも楽になると思います。単一の機能を極限まで短くすることには、Perl の美学に通ずるものがあると思います。言い換えればここは、Perl の隅を針で突く、プロジェクトページです。
Perl > Perl実験室でWeb雑考
このページでは、Webを漁りながら思ったことを書き留めていきます。
Perl > クエリを連想配列で受け取るスマートな方法
読み直してみるとこのページはわかりにくいコードを推奨しているような気がする
[perl] Perl > サーバーにアップロードしたcgiのエラーチェック
「cgiはローカルで動作確認済みのものをアップロードしてください。」共有サーバに無用な負担がかかるのを防ぐために規約にかかれている文言だ。つまり、サーバにおける正常な動作が保証されていないスクリプトは、サーバで走らせてはいけない、ということだ。ローカルで正常動作したものが、サーバで正常動作するという保証は無い。なぜなら、ローカルとサーバでは環境が異なるからだ。では動作確認をどのようにすればいいのだろうか。サーバ上での正常動作を保証するには、サーバ上で動作確認するしかあるまい。なぜなら、正常な動作の保証は実行環境とテスト環境が全く同じであるからこそなされるからだ。この項では、Perlで書かれたcgiプログラムの異常終了を正常終了したものとし、エラーメッセージを表示するサブルーチンの導入を行うことで、サーバ上でも動作の確認ができるようにする。
[perl] ブリコラージュ的 cgi
このページでは、ピンの設置方法について述べています。
サーバ上でファイルを書き換えるe.cgi(ProjectRotation8)
Webページをローカルで編集するとダウンロード、編集、アップロード、という手順をとらなくてはならない。リモートのディレクトリをマウント出来れば最高。手元にあるマシンが自分のマシンで無い場合はパスワードを入力。みんなで Webページ編集を前提にすればどうかな。
[cgi] サーバ上でファイル操作を行うtool.cgi
サーバ上でのファイル編集が出来ても、ファイル操作が出来ないと色々と面倒である。たとえば、ファイルをコピー、リネーム、ファイルのシンボリックリンク、パーティションの変更、などが出来ないとだめである。シェルの代替になるようなものが無いとね。
ファイル操作を行うフレームワークを作る
フレームワークということで、ファイル操作を行って、この結果を取得して、結果を出力するフレームを作る。
$cmd = 'rename("old","new")';
$ERROR = eval $cmd;
$BODY .= printf("%s : %s", $cmd, $ERROR);
怒られる前に