Googleを利用した検索ページの作り方


はじめに

http://search.net-newbie.com/ (PHP+PostgreSQL日本語マニュアル全文検索システム)は
従来 namazuで構築していましたが、 このたびGoogleを利用した検索に移行しました。
ここではその手法について解説します。

やりたいこと

  1. 検索対象コンテンツはここ(自サイト)に置きたい
  2. でも検索はGoogleに任せたい
  3. 検索対象コンテンツが複数のディレクトリに分かれて置いてあり、
    エンドユーザが検索する際に、検索対象ディレクトリを指定させたい

制限事項

JavaScriptを使っています。w3m などのテキストベースのブラウザでは、
自分で検索オプションを書いてやらないとだめです。

ディレクトリ構成

本検索サイトのディレクトリ構成は、以下のようになっています。

/─ VirtualHost 基準ディレクトリ
├─ affiliate.html (インクルードされるおまけ。本題には関係ありません)
├─ css/ (必須ではありません)
└─ gsearch.css (必須ではありません)
├─ favicon.ico なくてもいいですが、Apache の error_log が汚れるので置いてあります
├─ robots.txt これも同様の理由で置いてあります。中身はカラです。
├─ google.php この解説ページ。 最初は (s)html で書きはじめましたが、中で html や
JavaScritp のソースを取り込んで、さらにタグを 無効化しないと
いけなくなったので、やっぱり .php にしました。
├─ index.shtml DirectoryIndex で指定したトップページ。 affiliate.html をインクルードしたいので、
SSI(Server Side Include) が有効になるように .shtml にしています。
├─ js/ 今回は JavaScript を使いました
└─ gsearch.js ここで検索時のディレクトリ制限を行います
├─ pear/ pear のマニュアル(多数)
├─ php/ PHP のマニュアル(多数)
├─ pgsql/ PostgreSQL のマニュアル(多数)
├─ smarty/ Smarty のマニュアル(多数)

HTMLソース(index.shtml)

<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>
<html>
<head>
  <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
  <meta http-equiv='Content-Style-Type' content='text/css'>
  <meta http-equiv='Content-Script-Type' content='text/javascript'>
  <link rel='stylesheet' href='css/gsearch.css' type='text/css'>
  <script type='text/Javascript' src='js/gsearch.js'></script>
  <title>PHP+PostgreSQL/MySQL日本語マニュアル全文検索システム</title>
</head>
<body>
<div>
  <h1>PHP+PostgreSQL/MySQL日本語マニュアル全文検索システム</h1>
  <hr />
  <ul>
  <li><A HREF='/php/'>PHP 日本語マニュアル(2009/01/02)</a></li>
  <li><A HREF='/pear/'>PEAR 日本語マニュアル(2009-06-21)</A></li>
  <li><A HREF='/smarty/'>Smarty 日本語マニュアル(2007/05/04)</A></li>
  <li><A HREF='/pgsql/'>PostgreSQL 日本語マニュアル(8.4.0)</A></li>
  <li><A HREF='/mysql41/'>MySQL 日本語マニュアル(4.1)</A></li>
  <li><A HREF='/mysql51/'>MySQL 日本語マニュアル(5.1)</A></li>
  </ul>
  <form id='form1' action='http://www.google.co.jp/search'>
  <p>
     <strong>検索対象マニュアル</strong>
     <input type='radio' name='_dir' id='php'    value='php' 
        checked='checked'>PHP
     <input type='radio' name='_dir' id='pear'   value='pear' >Pear
     <input type='radio' name='_dir' id='smarty' value='smarty' >Smarty
     <input type='radio' name='_dir' id='pgsql'  value='pgsql' >PostgreSQL
     <input type='radio' name='_dir' id='mysql41' value='mysql41' >MySQL 4.1
     <input type='radio' name='_dir' id='mysql51' value='mysql51' >MySQL 5.1
  </p>
  <p>
    <strong>検索式:</strong> 
    <!-- 検索対象サイトを制限 -->
    <input type='hidden' name='as_sitesearch' value='search.net-newbie.com' />
    <!-- クエリーの文字コード(Input Encoding) -->
    <input type='hidden' name='ie' value='UTF-8' />
    <!-- 検索結果の文字コード(Output Encoding) -->
    <input type='hidden' name='oe' value='UTF-8' />
    <!-- 対象ディレクトリ制限用(Hidden Query - JavaScriptでセット)-->
    <input type='hidden' name='hq' id='hq'    value='' />
    <!-- 検索文字列入力ボックス -->
    <input type='text' name='q' id='q' size='40' maxlength='256' value='' />
    <input type='button' value='検索' onclick='on_submit()'>
  </form>
</div>
<div>
<p>
このページは従来 namazu で運用していましたが、Google に移行しました。<br />
<a href='google.php'>Googleを利用した検索ページの作り方</a>
</p>
</div>
<div>
<!--#include virtual="affiliate.html" -->
<p>
<a href='http://net-newbie.com/'>
  <img src="http://net-newbie.com/images/hand.up.gif" alt="up">
</a>
</p>
</div>
</body>
</html>
  

HTMLソースの解説

<form id='form1'
action='http://www.google.co.jp/search'>
フォームデータの送信先指定
<input type='radio' name='_dir' ... ユーザに選択させるマニュアルの種類。
このままだと '_dir' という変数も Google に送られてしまうので、
本来はこれを抑止した方がよさそうですが、方法がよくわかりません。
<input type='hidden' name='as_sitesearch' ... Google に対して、検索する「サイト」を制限させるための指定
<input type='hidden' name='hq' ... hq は Hidden Query(隠しパラメータ)で、その中身はいろいろ設定できるようです。
今回は、その中の 'inurl: ディレクトリ指定' を行います。
なお、hq にすれば、Google が表示する検索結果一覧画面の中の、
前回検索文字列ボックスに 'inurl: ...' が表示されないはずだったのですが、
現在は表示されてしまうようです(やり方が悪いのかも?)。
<input type='button' value='検索'
onclick='on_submit()'>
submit の前に JavaScript で hq 変数をセットするために
type='button' にしています。submit 操作は JavaScritpt 側で 行います。

JaveScriptソース(gsearch.js)

//=====================================================================
//  Google 検索フロントエンド   gsearch.js
//      2009/06/17 by M.Hotta
//=====================================================================

function    on_submit()
{
    var hq = document.getElementById('hq');
    hq.value = null;                            //  前回選択のクリア
    var ids = [ 'php', 'pear', 'smarty', 'pgsql', 'mysql41', 'mysql51' ];
    for (i in ids)  {
        var radio = document.getElementById(ids[i]);
//      alert('on_submit(): radio.id    = ' + radio.id      + "\n"
//          + '             radio.value = ' + radio.value   + "\n"
//          + '             hq.id       = ' + hq.id         + "\n"
//          + '             hq.value    = ' + hq.value);
        if (radio.checked)  {
            hq.value = ' inurl:' + radio.value; //  検索対象ディレクトリ制限
//          alert('on_submit(): hq.id    = ' + hq.id + "\n"
//              + '             hq.value = ' + hq.value);
            break;
        }
    }
    var form1 = document.getElementById('form1');
    form1.submit(); 
}
  

JavaScriptソースの解説

  1. ラジオボタン (name='_dir') にそれぞれ別個の id をつけており、 この中のどれが押されたかをチェックします。
    たとえば 'pear' が押された場合、radio.value に 'pear' が入ります。
  2. hq 変数に inurl: radio.value をセットして submit します。
  3. inurl: URL(ここではサブディレクトリ)指定
    URL に指定した文字列を含むものだけを検索対象とする。
    site: と inurl: の組み合わせでディレクトリ制限を実現します。
    よく考えると、as_sitesearch 変数自体を site: HOSTNAME/DIR/ にしてもいいですね。
    でも当初は DIR1 or DIR2 もできないかな、と思って inurl: を使ってみました。
    でも inurl: を2つ指定すると AND 条件になるようなのであきらめました。
    なんかあきらめてばっかだなー。ねばり気のない奴ですw

Google検索に関する資料集

以下のサイトを参考にさせていただきました。

up