1.023world - ヤドカリパークとマリンアクアリウム -

海洋の仕組みと細菌・微生物から学ぶマリンアクアリウムサイト

1.023world Facebook

結果 Oh! Life (旧ブログ)

懲りずに書いてみたりする結果オーライな日記

静的サイトのためのRORサイトマップ生成CGI

最近はアクアショップサイトなんかでもCMSの利用が増えてきましたが、それでもまだ古式ゆかしく静的なHTMLをソフトまたは手打ちでシコシコ作成しておられるショップサイトも少なくないでしょう (間違ってもバカにしてるつもりはありませんし、むしろ尊敬します)

そんなショップさんを応援すべく、少しでも他の CMS サイトに負けないためにも、ROR 形式のサイトマップXML(検索エンジン対策)を自動で生成してくれる CGI を作ってみました。
まずは流れを知るために、以下の解説を順にご覧ください。

ROR サイトマップとは?

以下のソースのような XML ファイルです。

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:ror="http://rorweb.com/0.1/">
  <channel>
    <title>ROR Sitemap for http://www.1023world.net/</title>
    <link>http://www.1023world.net/</link>
    <item>
      <link>http://www.1023world.net/</link>
      <ror:updated>2009-02-28T18:54:48+00:00</ror:updated>
      <ror:updatePeriod>weekly</ror:updatePeriod>
      <ror:sortOrder>0</ror:sortOrder>
      <ror:resourceOf>sitemap</ror:resourceOf>
    </item>
  </channel>
</rss>
</rss>

これは当サイトの場合のソースの抜粋例ですが、実際にはページ数の分だけソースは繰り返し長くなります。
内容的には、どのページがいつ更新されたか、そして更新頻度はどうか、みたいな情報がXMLの構文で羅列されています。
この XML ファイルをサーバーに置いて検索エンジンに渡すことで、リストされたサイト内のページをもれなくクロールさせることができます。

ROR 形式のサイトマップは、Google、Yahoo、MSN、すべての検索エンジンで利用可能な汎用フォーマットなので、これからサイトマップの準備を検討される方にはおすすめなフォーマットです。
ちなみにアクアショップさんじゃない方でも、必要であればご自由にお使いください (サポートはしませんが)

RORサイトマップ作成CGI 特長

  • CGI をサーバーに置いて呼び出すだけでRORサイトマップを自動生成
  • 簡易認証機能があるので、他人に実行させない
  • 他のサーバーにURLを送ったり、生成時にソースをコピーしたりファイルを作成したり等の手間が一切不要

RORサイトマップ作成CGI 利用条件

  • 独自ドメインの方
  • サーバーで CGI が使えること
  • サーバーに Jcode.pm がインストールされていること

RORサイトマップ作成CGI 設置手順

  1. CGI のプログラムソースをメモ帳(あるいはテキストエディタ等)にコピペして「setSitemap.cgi」と言う名前で保存します。
  2. 必要であればご利用のサーバーに合わせて1行目の Perl のパスを書き換えます。
    #!/usr/bin/perl または #!/usr/local/bin/perl など)
  3. 次に8行目のパスワードをあなただけのモノに必ず書き換えておいてください。
  4. 万一、サイトマップで除外したいページがある場合は、14行目の @no と言う配列にファイル名またはディレクトリ名をルートからの絶対パスで追加してください。
    例えば、http://あなたのドメイン/secret.html を除外したければ、 /secret.html を追加します。
    また、http://あなたのドメイン/member/ 内のすべてのページを除外したければ、/member/ を追加します。
    (これらの例を既にソースに入れてあります)
  5. 作成した CGI ファイルを、サーバーのルート(トップページを置いてる階層)にアップロードします。
  6. CGI ファイルのパーミッション(アクセス権)を 755 にします。
    (サーバーによっては 755 以外の場合があります)
  7. http://あなたのドメイン/setSitemap.cgi?パスワード にアクセスします。このURLが今後サイトマップを更新するURLとなります。
    仮にあなたのドメインが abc.com で、パスワードを abcd1234 としたなら、http://abc.com/setSitemap.cgi?abcd1234 へのアクセスとなるはずです。
    このアクセスにより、その時点でのサイトマップが ror.xml と言うファイル名でルートに生成(更新)されます。
    生成後のサイトマップのURLは http://あなたのドメイン/ror.xml です。
    (Firefoxだとタイトルしか出ないかも知れませんが、ソースを開けばサイト内のページがすべてリストアップされているのが確認できると思います)
  8. 続いて、あなたのサイトのトップページのヘッダ内(<head>この中</head>)に、以下のタグを埋め込んでおきます。改行せずに一行で書いてもOKです。
    <link rel="alternate" type="application/rss+xml"
    href="http://あなたのドメイン/ror.xml" title="ROR 0.1" />

    これで、次回の検索エンジンのクロールでサイトマップが読み込まれ、リストされたすべてのページが今後のクロール対象となるでしょう。
    あとは、今後サイトを更新するたびに 7. へアクセスして、その都度サイトマップを最新のモノに更新しておいてください。

RORサイトマップ作成CGI のプログラムソース

#!/usr/bin/perl

### make: http://YOURDOMAIN/setSitemap.cgi?(password)
### view: http://YOURDOMAIN/ror.xml
##################################################

### password
my $pwd = "abcd1234";   # set your original password.

### ROR file name
my $ror = "ror.xml";

### noindex files or directory, from root path.
my @no = (
  "/secret.html",
  "/member/",
);

### updatePeriod:
### always,hourly,daily,weekly,monthly,yearly,never
my $up = "monthly";

##################################################

use Jcode;

&viewXML if ($ENV{'QUERY_STRING'} ne $pwd);

my $no = ",." . join(",.",@no) . ",";

my(@html,$xml);
&getHTML("./");
&setXML;

print qq|Content-type: text/xml; charset="UTF-8"\n\n$xml|;
exit;

sub viewXML {
  print "Location: http://$ENV{'HTTP_HOST'}/$ror\n\n";
  exit;
}

sub getHTML {
  my $dir = $_[0];
  my @file = &getDir($dir);
  foreach my $file (@file) {
    my $path = "$dir$file";
    next if ($no =~ /,\Q$path\E\/?,/);
    &getHTML("$path/") if (-d $path);
    next if ($file !~ /\.html?$/i);
    my $last = (stat($path))[9];
    $path =~ s/^\.+|(\/)index\.html?$/$1/ig;
    push(@html,"$last\t$path\t$up\t\n");
  }
}

sub setXML {
  @html = reverse sort @html;
  foreach (@html) {
    my($last,$path,$up) = split(/\t/,$_);
    my($year,$mon,$day,$hour,$min,$sec) = &getTime($last);
    $last = "$year-$mon-$day" . "T$hour:$min:$sec+09:00";
    $xml .= <<"EOF";
		<item>
			<link>http://$ENV{'HTTP_HOST'}$path</link>
			<ror:updated>$last</ror:updated>
			<ror:updatePeriod>$up</ror:updatePeriod>
			<ror:sortOrder>0</ror:sortOrder>
			<ror:resourceOf>sitemap</ror:resourceOf>
		</item>
EOF
  }
  $xml = <<"EOF";
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:ror="http://rorweb.com/0.1/">
	<channel>
		<title>ROR Sitemap for $ENV{'HTTP_HOST'}</title>
		<link>http://$ENV{'HTTP_HOST'}/</link>
$xml	</channel>
</rss>
EOF
  &setFile("./$ror",Jcode->new($xml)->utf8);
}

sub getDir {
  my $dir = $_[0];
  opendir(DIR,$dir) || return ();
  @_ = sort readdir DIR;
  closedir(DIR);
  splice(@_,0,2);
  return @_;
}

sub setFile {
  my($file,@data) = @_;
  open(OUT,"> $file");
  seek(OUT,0,0);
  print OUT @data;
  truncate(OUT, tell(OUT));
  close(OUT);
  chmod(0666,$file);
}

sub getTime {
  my $time = $_[0];
  $ENV{'TZ'} = "JST-9";
  my($sec,$min,$hour,$day,$mon,$year,$week) = localtime($time);
  $year += 1900;
  $mon = sprintf("%02d",$mon+1);
  $day = sprintf("%02d",$day);
  $hour = sprintf("%02d",$hour);
  $min = sprintf("%02d",$min);
  $sec = sprintf("%02d",$sec);
  $week = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat')[$week];
  return ($year,$mon,$day,$hour,$min,$sec,$week);
}

うまくコピペできない場合は、こちらを開いてご利用ください。

注意事項など

  • 静的HTMLではないサイト構造の方(ブログ等)は利用できません。あくまでHTMLファイルが対象です。
  • サイトマップの生成にはサーバーにある程度の負荷が掛かるので、必ずパスワードを設定して自分だけがアクセスできるようにしてください。また、自分以外の方が触るパソコンでは、サイトマップ更新用URLはブックマークしない方が無難です。
    ちなみにパスワード無し(あるいは間違えると)でアクセスすると、ror.xml にジャンプする仕組みになっています。
  • サイト内のすべてのページ(拡張子が .htm.html のもので大文字小文字問わず)が全て対象になるので、都合の悪いページは予め @no に設定しておいてください。
  • サイトマップの生成に要する時間はページの量に応じて長くなります。
  • サイトマップはページの更新日時順に降順でソートされます。
  • CGI ファイルを作成する際の文字コードは意識する必要はありません (Shift_JIS でOK)
  • updatePeriod 要素は全ページ共通の設定となります。weekly か monthly あたりで良いと思いますけど。
  • sortOrder 要素は全ページ 0 を割り当てています。これは0以外を入れたらどうなるのかよく判りません(汗)
  • プログラムはソースを簡潔にするため、必要最小限の構成となっています。不便な点や改良点があれば自由にいじってお使いください。
  • なるべくサーバーに依存しないように組んでありますが、最低限 Jcode が使えるサーバーが必要です。
  • 尚、全てのサーバーでの動作を保証するモノではありませんので、解説通りに設置して動かない場合は諦めてください(汗)
    但し、海水関連ショップの方ならご相談に載ります。
    info@1023world.net まで。

その他、何かあればコメント欄にどうぞ。

こちらのエントリーもどうぞ♪

点線or波線が崩れるIEのCSSバグ回避

3年くらい前にやってたアメバブログでも書きましたが、未だに役に立ちそうな情報なので、また公開したいと思います。

HTML + CSS のコーディングに於いて、レイヤのサイド(left or right)に 1 ピクセルの点線や波線を施した場合、IE では縦スクロールしただけで見事に崩れてしまう不具合をご存じでしょうか?
こんな感じです。

1ピクセルの点線や波線は、IEでの縦スクロールにて不具合が発生する

これは dashed (波線) の場合ですが、これを仮に dotted (点線) を使っても同様に崩れます。
しかし、ボーダーの太さを 2 ピクセル以上に設定すると不具合は発生しません。 1 ピクセル時のみの不具合のようです。

蛇足ですが、IE 6 では 1 ピクセルの点線が 1 ピクセルの波線とまったく同じレンダリングをしてしまうと言うバグもあります(笑)

さて、この現象の回避策を、たまたま CSS を触っていたときに発見しました。
一見ボーダーとは無関係な「背景」に関する CSS を追加してやるだけで見事に解消されるのです。

このように body に対して背景固定のCSSコードを一行追加してやります。

body {
  background:url(null.gif) fixed;
}

たったこれだけで、あんなに崩れていたボーダーが見事に改善されます。
もし body に対して既に背景を指定している場合は、そこへ fixed のみ追記すればOK。

尚、この時の null.gif は実際に存在しないパスでも良いのですが、サーバーにエラーログが残るのがイヤなら 1×1ピクセル程度のダミー画像を用意されると良いでしょう。但し、パスを空にすると改善しないので、何かしらパスの指定が必要になります。
その他、無駄にリピートさせるとブラウザの負荷にもなり兼ねないので、no-repeat も付け足すと良いと思われます。

この措置により、以下のように改善されます。

背景に適当な画像を割り当てて固定(fixed)するだけで不具合が回避される

ちなみに、IE の点線の処理方法を見ていると、白紙に黒い点々を描くと言うよりは、穴を空けた白紙を黒い紙の上に載せて点線に見立てているような感じがします。
それ故、このような回避策が得られたのでしょうか?

いずれにしても IE には早く改善して貰いたいモノです。
が、この不具合は IE 8.0 ベータでもまだ見られますけど(汗)

こちらのエントリーもどうぞ♪

タグクラウドというもの

タグクラウド
直訳すると「タグの雲」を意味し、雲のように表示されるタグ文字列が大小さまざまに浮かんでいるように見えることからこの名前が付けられた。
ウィキペディアより引用

今までみなさんのブログでこの「タグクラウド」というものを見かけることはあっても、あまりクリックもしたことがなかったし、興味もなかった。と言うか、そもそも何のためにあるのかいまいちよく判らなかった。しかし、最近になって自分の記事がぼちぼち増えてくると、なんとなくその存在意義が見えてきたように思う。

まず一般的にブログとは、記事が延々と増殖していくにしたがって、古い記事がどんどん奥へ奥へと追いやられてしまう仕組みだ。そうなってくると、一見有り難そうに見える「カテゴリー」や「アーカイブ」などの誘導だけでは、とてもじゃないが必要な情報を思うように辿ることはできなくなってくる。記事が多ければ多いほど、分類と時系列だけでは目的地が一向に見えてこないのだ。

しかしインターネットをブログから始めた世代にとっては、これはごく自然で当たり前の事なのかも知れない。そんな流れを見て僕も少しでも馴染もうと励んでいたが、いまひとつこのブログというモノは苦手な分野のひとつだった。そしてやはりそれは僕がソフトや手打ちでウェブを作り始めた世代だからだろう、と理由づけていたように思う。

でもよく考えてみると、今さらながら悟ったかも知れない。ブログとはまさに日記なのであって、ホームページとは比べるモノではないということを。
おわり。

いや、終わらない。

ブログを見ていていつも感じていたこと。それは僕が知っているホームページの快適さを、どうしたらブログで実現できるだろう、ということだ。そして真っ先に思いつくもののひとつに、サイトマップが挙げられると思う。先日のサイトマップXMLの話ではなく、本来のサイトマップの方だ。

例えば僕の1.023worldでは、全てのページからほぼ一発で目的地に移動できるようになっている。サイトマップの便利さを、全て左メニューに集約してあるのだ。

20090306-left-menu

また、移動中は常に該当コンテンツのサブメニューが自動的に開くようになっていて、且つ現在地もハイライトしてあるので、まず迷子にはなりにくいはずだ。これは僕なりに考えたユーザビリティの形である。
そしてそれは、本来ネットサーフィンとは情報の収集にこそ集中すべきであって、それ以外の部分でリソースを消費させるのはナンセンスだ、と言うところから来ている。
ココは誰。私はどこ。これではうっかり目的も忘れてしまいそうだ(笑)

そこでタグクラウドですよ。
そんなブログとホームページに見られる深い溝を少しでも埋めてくれるのが、僕はタグクラウドかも知れないと思えてきました。

ブログのカテゴリーがホームページで言うメインコンテンツならば、タグクラウドはホームページで言うサブメニューに近い期待感がありませんか?
どこにどんな情報があるのかカテゴリーだけでは判りにくいブログにとって、タグクラウドはまさに情報そのものの在処を示す道標と言えそうです。
うーん。。。なんかウェブ屋っぽい講釈だ(汗)

さて、これで右下に新設したタグクラウドが神々しく見えてきましたか?(曝)

実は僕は今まで記事にタグ自体打っていませんでしたが、このためにわざわざ過去に遡って全ての記事にタグ打ってきたっての。
しかも設置するのにちょっと手間取っちゃったので、また備忘録しておきます。
WordPress でタグクラウドを設置する方法は主に以下の2通りありました。

  1. ウィジェットでサイドメニューに割り当てる方法
  2. テンプレートに直接タグを挿入する方法

僕は1.を済ませてから2.の存在を知ったのでムキーでした(笑)

WordPress では少し前からタグクラウドが標準装備だったそうで、管理パネルの「外観」から「ウィジェット」を選択すれば簡単に配置することが出来るのですが、僕の場合はテンプレートが古くて対応していませんでした。しかも1.023world専用に組んであったし。
で、わざわざ古いテンプレートをウィジェット対応に書き直し、実装が完了したと思ったら、実は他のテンプレート同様、PHPのタグを一行書くだけで実装可能だったのでした(曝)

ちなみにこんなの。

<?php wp_tag_cloud(); ?>

たったこれっぽっち書くだけでOKって、うおーいっ。
この記事ホントは、この「うおーいっ」が言いたいだけだったりして(汗)

最後に、以下のタグクラウドも検討したけど、日本語が文字化けすることと、仮に日本語対応にすると軽く2MBくらいになっちゃうので却下しました。
FLASHタグクラウド WP-Cumulus
日本語使わない人にはお勧めかも♪

こちらのエントリーもどうぞ♪