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

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

1.023world Facebook

結果 Oh! Life (旧ブログ)

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

そろそろ透過PNG?

IE 7.0

IE 7.0 がリリースされてから、もうかれこれ2年以上が経過し、一方、IE 6.0 のシェアはそろそろ20%を切ったあたりだそうです。・・・って、まだ全然多いんですけど(汗)

とは言え、IE 7.0 になってから、ひとつだけ助かったことがあります。それは、24ビット PNG のアルファチャンネルに対応してくれたことです。これでようやく透過 PNG が貼れるようになりました。

透過PNGのサンプル

と言いたいところですが、まだ IE 6.0 ユーザーが残ってます。
そんなモン早く窓から放り投げてください(笑)

ちなみに IE 6.0 では、こんな風に表示されちゃいます。

透過PNGをIE6.0で表示した場合

なので、もし現時点で透過 PNG をウェブで使おうと思ったら、AlphaImageLoader フィルター(IE独自拡張)を活用せざるを得ないのが現状です。
(IE6ユーザーを切り捨てるなら話は別ですが)
幸いこれを使えば、辛うじて IE 6.0 でも透過 PNG を表示させることができます。

と言ってもコレ、ちょい面倒くさいんですよね。。。

AlphaImageLoader をどう使うか

例えば、透過 PNG を CSS の background 属性に限定して記述するなら、通常の background 属性の記述に続いて、filter 属性への AlphaImageLoader の設定と、アンダースコアハック(underscore hack)による background の消去を行うことで適用できます。(アンダースコアハックはIE6のみに適用させる場合に用いるハック方法)
但し、縦横のサイズが PNG と同一のレイヤに対しては問題ありませんが、PNG よりも大きなレイヤに背景として配置するような場合には注意が必要です。(AlphaImageLoader フィルターの sizingMethod オプションを crop にするか scale にするか等)

しかし、AlphaImageLoader フィルターを、HTML 内の <img> タグで貼られた透過 PNG に適用させる場合は、単に <img> タグに対して AlphaImageLoader フィルターを適用させただけでは、src 属性で指定された元々の PNG が残ったままなので、IE6 では相変わらず非透過の PNG が表示されたままとなります。これは外部 CSS ファイルで記述した場合でも、 <img> タグへ style属性で記述した場合でも同様です。そのため <img> タグの src 属性に透明 GIF を割り当てる等の最終処理が必要になります。そしてこの場合は何らかの JavaScript での処理に頼ることになります。

また、W3C に準拠した Valid でクリーンなソースを壊したくない場合や、ブラウザの独自拡張になるべくなら頼りたくない場合など、おかしなハックやコメントの記述をためらうこともあるでしょう。そう言う理由からも、このようなややこしい処理は初めからすべて JavaScript に丸投げする方法を推奨します。そうすることで、必要悪は最小限に抑えられるでしょう(苦笑)

ちょっと検索してみたら、この機能を持った JavaScript モジュールがいくつか配布されているようでした。ただ、実際にコードを見てみると、必要のない機能が多かったり、無駄にファイルサイズが大きかったりするので、PNG だけの処理には持てあますかも知れません。たかだか IE6 のためだけに資源を無駄に使うこともありませんし。

PNG → AlphaImageLoader 自動転換 JavaScript コード

そこで、PNG だけを処理してくれる JavaScript を組んでみました。(昔組んだものを少しいじっただけですが)
例によって、ページのヘッダに事前に読み込んでおくだけで、あとは自動的に処理してくれるものです。

このコードは、外部 CSS ファイルや HTML 内の <style> タグによる CSS や <img> タグの PNG をスキャンして、自動的に AlphaImageLoader を適用します。但し、<img> タグへの置換用に、予め透明 GIF をサーバーのどこかにアップロードして、ie-png.js 内の gif 変数に絶対パスで設定しておいてください。

変換対象
外部 CSS ファイル
  • background:url(PNG-URL) [color repeat position]
  • background-image:url(PNG-URL)
  • PNG 画像パスは自動的に解析し割り当てるので相対パスでもOK
  • PNG 画像パスをクオート(シングル・ダブル)で囲んであってもOK
内部 <style> タグによる CSS
  • background:url(PNG-URL) [color repeat position]
  • background-image:url(PNG-URL)
  • PNG 画像パスは自動的に解析し割り当てるので相対パスでもOK
  • PNG 画像パスをクオート(シングル・ダブル)で囲んであってもOK
<img> タグの PNG
  • 予め透明 GIF をサーバーにアップロードして、JavaScript コードにその透明 GIF 画像パス(絶対パス推奨)を設定してください
    var gif = 'アップロードした透明GIFの絶対パス';
  • PNG 画像パスは自動的に解析し割り当てるので相対パスでもOK

テスト結果:サンプルページ * IE 6.0 で見ないと効果が判りません
ダウンロード:ie-png.js

ひとりごと

確か、IE 6.0 だけじゃなくて、IE 5.5 とかにも AlphaImageLoader は使えたと思ったのですが、今手元の IETester で試してみると IE 5.5 では AlphaImageLoader による透過 PNG が表示されません(汗)
一応、コード自体は IE 5.5 でも走るように書いたつもりですが、もし動作確認がとれた方はご一報いただけると嬉しいです。

また、インライン CSS 分の画像パスや絶対パスによる記述分は良いとして、外部 CSS ファイル内の相対パスによる画像パスについて、なんかもっとうまく処理する方法はないかしら。例えば、外部 CSS ファイルを HTML とは別の階層から呼び出していた場合に、相対パスだと AlphaImageLoader に渡す画像パスがずれてしまうので、今は地道に生成するようにしてあります。

その他、background 関係以外の画像適用 CSS プロパティ(list-style-image とか)までは面倒なので実装を省略しました(汗)

以下、一応 ie-png.js のコードです。

var gif = 'null.gif';

var env = new Object;
env.ua = navigator.userAgent.toLowerCase();
env.win = (env.ua.indexOf('windows') != -1)? 1: 0;
env.ie = (!window.opera && env.ua.indexOf('msie') != -1)?
           Number(env.ua.charAt(env.ua.indexOf('msie ') + 5)): 0;

var url = new Object;
url.host = 'http://' + window.location.host;
url.path = window.location.pathname.replace(/^(.*?)/[^/]*$/,'$1') + '/';

function setOnload(func){
  (window.addEventListener)? window.addEventListener('load',func,false):
  (window.attachEvent)? window.attachEvent('onload',func):
  window.onload = func;
}

var checkPNG = {
  CSS: function() {   // background, background-image propaty only.
    if(!env.win || env.ie > 6 || env.ie < 5) return false;
    var path = new Array();
    var num = 0;
    var node = document.getElementsByTagName('head')[0].childNodes;
    for(var i=0;i<node.length;i++){
      if(node[i].nodeName.match(/^style$/i))
        path[num] = url.host + url.path;
      else if(node[i].nodeName.match(/^link$/i) &&
          node[i].getAttribute('rel') &&
          node[i].getAttribute('rel').match(/stylesheet/i)){
        var href = node[i].getAttribute('href');
        if(href.match(/^//)) path[num] = url.host + href;
        else if(!href.match(/^https?:///))
               path[num] = url.host + url.path +
                 href.replace(/^(([^/]*/)*).*?$/,'$1');
        else path[num] = href;
      }
      if(path[num]) num++;
    }
    for(var i=0;i<document.styleSheets.length;i++){
      var rule = document.styleSheets[i].rules;
      for(var j=0;j<rule.length;j++) {
        var png = checkStyle(rule[j],'background');
        if(!png) png = checkStyle(rule[j],'backgroundImage');
        if(!png) continue;
        png = (png.match(/^//))? url.host + png:
          (!png.match(/^https?:///i))? path[i] + png: png;
        rule[j].style['filter'] =
          'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' +
          png + ',sizingMethod=crop)';
      }
    }
    function checkStyle(obj,propaty){
      var value = obj.style[propaty];
      if(!value || !value.match(/.png/i)) return false;
      var png = value.replace(/^.*?url(["']*([^"']+.png)["']*).*$/i,'$1');
      obj.style[propaty] = '';
      return (!png.match(/^[^"']+.png$/i))? '': png;
    }
  },
  HTML: function(){   // '<img>' elements only.
    if(!env.win || env.ie > 6 || env.ie < 5) return false;
    var img = document.getElementsByTagName('img');
    for(var i=0;i<img.length;i++){
      var src = img[i].getAttribute('src');
      if(!src.match(/.png/i)) continue;
      if(!src.match(/^https?:///i)) src = url + src;
      img[i].setAttribute('src',gif);
      img[i].style.filter =
        'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=' +
        src + ',sizingMethod=scale)';
    }
  }
}

function onloads(){
  checkPNG.HTML();
}

checkPNG.CSS();

setOnload(onloads);

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

重複コンテンツ正規化の効果

重複コンテンツの正規化と言っても、あまりピンとこないかも知れない。
アクアリウムサイトではあまり該当のサイトは見かけないし。
でも例えばうちがそうです(汗)

重複コンテンツとは?

重複コンテンツというのは、主に CGI や PHP なんかが動的に生成するページなどで発生します。静的な HTML で発生してたら、それは意図的な何か陰謀を感じます(曝)

例えば、見た目はほぼ同じページなのに、URL が微妙に違うってことありますよね?
こんな感じで。

http://www.1023world.net/city/eiji
http://www.1023world.net/city/eiji?menu=guestbook&date=20090207
http://www.1023world.net/city/eiji?menu=guestbook&date=20090208

これはどういうものかと言いますと、「基本的には同じページなんだけど、データや表示方法を切り替える目的で、プログラムに引数を渡して処理させるような場合」などによく用いられる URL 形式です。
但し、上記のURL例の場合は表示内容がかなり変わるため厳密には重複コンテンツにはならないと思いますが、よくある通販ページ等で、単に商品の並び替えソートを行うようなページは、記載順が違うだけで内容は同じなので、そういうものは重複コンテンツと見なせます。

また、単に以下のようなケースもあります。

http://1023world.net/
http://www.1023world.net/

www に対するサブドメインの処理はサーバーの設定によっても違いますが、多くの場合、上記のケースは同じページを指しますよね。こういうものも重複コンテンツになります。

重複コンテンツを正規化する

では、それがどうしたの?と言われそうですが、実はこれらのうんちくは他の誰でもない検索エンジンらが騒いでいることです(笑)
なんて言うと叱られるのできちんと説明しますと、要するに同じ内容なのに URL がいくつもあると、検索エンジンはそれだけ多くのページを巡回しなければならないし、保存データも多くなるので資源の無駄だから、もっとこれらを最適化しなさいよ。と言うことです。

とは言え、それらを無くすことが出来るなら、初めからそのような構造を作りませんよね。
もし無くせるならそれに越したことはありませんが、大抵の場合これは「必要悪」です(汗)
ですから、「せめてページでこのように宣言しなさいよ」と、検索各社が正式に発表したそうです。

<head>
...
<link rel="canonical" href="本来の正式なページのURL" />
...
</head>

重複コンテンツに該当するページにこのように記述することで、「あぁ、このページはあのページのダブりね。OK!」と、検索エンジンがスマイルになるのです。
もちろん、ダブりに該当するページ全てに記述が必要ですね。
また正式ページにも記述して問題ないと思います。その方が判りやすいかも。

ちなみに多くの場合は CGI や PHP が対象だと思うので、その場合は HTML に記述するようにはいきません。該当のプログラムのテンプレートのヘッダに、動的な URL が割り当てられるように <link rel=”canonical” href=”正規な動的URL”> タグを適切に記述しなければなりません。詳しくは利用しているプログラムのヘルプを。

最終的にそれらの関係にあるページ群には、それぞれ以下のように記述させます。

Aページのヘッダ内
<link rel="canonical" href="AページのURL" />
Aページのダブりページ1のヘッダ内
<link rel="canonical" href="AページのURL" />
Aページのダブりページ2のヘッダ内
<link rel="canonical" href="AページのURL" />

これで検索エンジンにやさしいサイトに昇格です(笑)

1.023world の場合

今回、当サイトでも一部のページで重複コンテンツの正規化を行いました。
超ヤドカリ図鑑の以下のようなURLパターンのページがすべて対象です。

カシワジマヒメホンヤドカリ/Pagurixus fasciatus Komai & Myorin, 2005 の場合

和名 URL
http://www.1023world.net/カシワジマヒメホンヤドカリ
学名 URL
http://www.1023world.net/Pagurixus-fasciatus

そうです。これらは URL こそ異なりますが、同じページを指しています。
なので、現在これらのパターンで形成されている重複 URL は、全て和名 URL を正規 URL に設定しました。

既にお判りのように、まるっきり異なる URL 同士を関連づけることになるので、実験も兼ねてました。また、検索各社が内部処理に役立てるだけなのか、あるいは SERPs(検索結果)にも反映されるのか、それも実験の目的でした。

ところで、そもそも超ヤドカリ図鑑では何故こんな URL 形式が採用されたかと言いますと、

  1. 目的のヤドカリのページに容易に辿り着けること ( URL の簡略化)
  2. 学名でも和名でも辿り着けること (グローバル?)
  3. 子供でも簡単に辿り着けること (広いターゲット層)

このような意図があります。
「 1.023world のトップページ URL に、調べたいヤドカリの名前を付け足すだけでOK!」というコンセプトです。

wiki もこんな感じですよね。
でも、別に wiki を目指した訳ではなくて、単に検索でヒットして欲しいから(笑)
URL 自体にキーワードが入っていると、検索結果への効果が違いますからね。
最近はあまり影響が見られなくなったようだけど(汗)
いや、あくまでも真の目的は上記の意図1~3ですから、お間違えなく(汗)

で、実際に検索テストをおこなってみたら、3/15時点で Google では既にこれが完璧に適用されていました。この措置は2月の末くらいに施したので、およそ半月が経過していますが、さすが Google は仕事が速いです。
それに引き替え Yahoo と MSN は。。。未だ華麗にスルーですね(汗)

以下、3/15時点での検索各社の挙動です。

Google
和名で検索しても学名で検索しても、正規化の指示通り和名 URL を返してくれます。これは単に内部アルゴリズムのためだけの正規化ではなく、SERPs への反映にも利用されているのが伺えます。
Yahoo
ヤドカリの種によっては和名 URL を返したり、学名 URL を返したり、特に何も考えて無さそう(苦笑)。多分、バックリンクの有無にも影響されているのでしょう。
MSN
学名で検索しても和名で検索しても、意地でも学名 URL を示す(曝)

すべてのヤドカリを検索した訳ではないので、上記はあくまでも参考例としてお受け止めください。

こうして今日もまたひとつ、 Google のサービスの良さを実感したのでした♪

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

WordPress高速化その後の経過報告

えー。まず事前案内から。

実は今月の投稿の約9割は、WordPress の予約投稿機能によるものです(汗)
今これを書いてる日付も本当は3/14ですが、今日のこの投稿内容で時系列が少し可笑しくなる恐れがあるので、予めお断りしておきます(曝)

先日(僕にとっては本当に昨日だけど、この投稿が公開される時点では一週間前になる)WordPress の高速化 と言う投稿をしました(と言ってもその投稿自体書いたのは今を遡ること2週間前になる)が、その後の効果を報告しておきます。
(あー。くどいので文中に時系列の解説はもう入れません)

QoSアラート再び

実はこの WordPress の高速化を実施する前までは、特に恐らく WordPress の最新版 2.7.1 をインストールしてからは、サーバーのメモリ使用率は一日あたり約10回前後のアラートが発生していました。
以前、このサーバーの下位プランを借りた時点ではアラートなんて出てませんでしたが、調子に乗ってあれやこれや回すようになったら、すぐにメモリが厳しくなってしまい、ものの3ヶ月ほどで現在の上位プランに移行せざるを得ませんでした(汗)
でもその後しばらくはまた平穏な日々が続いていたはずでしたが、今年の2月に入ってくらいかな、またアラートがポツ、ポツと出始めるようになってしまったのです。

ちなみに今僕が使ってるサーバーは VPS なので(厳密には性能保証プランの方)、管理画面が Virtuozzo (仮想化ソフト)やら Presk (コントロールパネル)やらが利用できるのですが、その Virtuozzo の方でリソースやら QoS アラートやらがモニタできるようになってます。

で、このアラートにも段階があり、普段出ていたのはソフトリミットの方で「イエローゾーン」と呼ばれています。これは、「契約しているプランの保証値に近づいてるぞ!」というものです。
と言っても、仮にコレを越えてもハードリミットまでの余裕があればそっちに回るので問題はありません。

が、ここ最近はまた契約初期のように「ブラックゾーン」と呼ばれるハードリミット越えが見られ始めていました。またかよ、と。
多分そのせいで WordPress が転けるようになり始めたんだと思います。
でも、こりゃどげんかせんといかん。
と言う経緯があっての、先日の WordPress の高速化 でした。

WordPress高速化の結果報告!

長くなりましたが、結果報告です。
なんと、これを実施した3/9以降、まだ一度もアラートは出てません!
ブラックどころかイエローすら見あたりません。
こりゃ凄い!!

いやぁ、ダメもとで試してみたMySQL のクエリキャッシュと、WordPress のコンテンツキャッシュの設定でしたが、なんとまあコレが覿面だったようです。

以下は、3/8まで出ていたアラートのログ。

20090321-qos-alert

また、平常時でもメモリ使用率はほぼ安定して40%台をキープしています。とてもこれがフローするとは今のところ思えません。

僕はサーバー関係は専門外でサッパリなのですが、これでしばらくは一安心です。
だったらルート権限付きのサーバーなんか借りるなって話ですが。。。汗

僕のようにリソースで困ってるサーバー初心者の方、もし WordPress を使ってるなら高速化をオススメしますです。

でも、早くも問題が・・・

ところで MySQL の状態を phpMyAdmin で見てみたら、なんか早くも Qcache_lowmem_prunes の値が現れていた。

20090321-phpmyadmin

Qcache_lowmem_prunes
新しい照会をキャッシュするためにメモリを解放するべく、キャッシュから削除された照会の数。この情報は照会キャッシュのサイズを調整するときに便利です。照会キャッシュがキャッシュから削除する照会を決定する際には、最後に使われた時刻が最も古いものから削除する戦略をとります。

これ、今 query_cache_size の値を 24M にしてあるんだけど、もう少し挙げた方が良いのかなぁ。
ま、ブログの方は閲覧者が少ないし、そこまで神経質になることないのかな?
サーバー先生。。。

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