utf-8で記述されたページに、フォームで Namazu の検索欄を設けたとする。 ここから検索を行うと、文字化けが生じる。 これを解決するための一つの方法は、ラッパープログラムを介することである。 具体的には、utf-8の文字コードをeucに変換するソフトを介して Namazu にアクセスする。 namazuでutf8ファイルの検索 (www.keknet.net) というページはこれを行っている。これを元にして、 自分でプログラムを作ってみた。次のサンプルである。
#!/usr/bin/perl
use CGI;
use Text::Iconv;
use CGI::Lite;
my $converter = Text::Iconv->new("UTF8", "EUC-JP");
my $cgi = new CGI;
my $new_query = $converter->convert($cgi->param('query'));
$uencode = url_encode($new_query);
print "Location: http://marinkyo.que.jp/cgi-bin/sercxo/namazu2.cgi?query="."$uencode\n\n";
ところが上記の版では動かないことがわかった。 以下原因と対策を述べる。
私が利用しているプロバイダでは、 Text::Iconv がインストールされていなかった。 止むを得ず、自分でインストールした。
Iconv で変換前と変換後の文字コード種類を指定するが、 文字コード名にばらつきがあるようだ。 私が参考にしたのは、Ruby レシピブックのp.39で、 ここにある文字列で文字コード種類を指定したところ、変換された。 大文字小文字の区別も重要。
検索においては、検索するキーワード(検索式)だけでなく、 CGI 変数も指定しなければならない。 CGI 変数の例は、Namazu のマニュアルの、 form の設定 という個所に記載されている。これを引き渡す必要がある。
最初は、たとえば、表示言語を引き渡すために、
次のようなことを考えていた。
$ulang = url_encode($cgi->param('lang'));
print "Location: http://marinkyo.que.jp/cgi-bin/sercxo/namazu2.cgi?query="."$query&lang="."$ulang\n\n";
しかしこの方法では、表示言語以外の CGI
変数に対して同様なことを繰り返す必要があり、面倒である。
今回は、CGI 変数 query のみに対して utf-8 への変換を行えばよい。
そこで、cgi 変数の query クラス変数のみを更新して、
メソッド query_string を呼び出せばよいと考えた。
これならば、どの CGI 変数が定義されているかを考える必要はない。
以上を合わせて、次が改良版となる。
#!/usr/bin/perl -I/$HOME/...
use CGI;
use Text::Iconv;
use CGI::Lite;
my $converter = Text::Iconv->new("UTF-8", "eucJP");
my $cgi = new CGI;
my $new_query = $converter->convert($cgi->param('query'));
$cgi->param('query', $new_query);
$query_str = $cgi->query_string;
print "Location: http://marinkyo.que.jp/cgi-bin/sercxo/namazu2.cgi?"."$query_str\n\n";
これは必ずしもUTF-8とは関係ないが、文字化け対策として乗せておく。 あるとき、次のように環境設定して cron で起動させたが、タイトルと要約文が文字化けする。 それどころか、キーワードでの検索にも該当文書が表示されない。
LANGUAGE="ja_JP.EUC";export LANGUAGE $HOME/local/bin/mknmz -O $HOME/local/var/namazu/index $HOME/internet/www.ne.jp/asahi/music/marinkyo
何だかわからないが、環境変数を沢山設定した。
LC_ALL=ja_JP.EUC; export LC_ALL LANG=ja_JP.EUC; export LANG LANGUAGE="ja_JP.EUC";export LANGUAGE
こうしたところ、タイトルと要約文の文字化けはなくなった。もちろん、該当文書も表示される。 (2009-11-09)
今まで使っていたホスティングのサーバとは別に、 新たなサーバが使えることになった。こちらについても Namazu を乗せた。 ただし、比較のために分かち書きに Kakasi でなく Mecab を用いた版である。 こちらのラッパープログラムも必要なので、今度は Ruby で書いてみた。 簡単だと思いきや、思いのほか苦労した。
#!/usr/local/bin/ruby
require 'cgi'
require 'iconv'
cgi = CGI.new
new_query = CGI.escape(Iconv.conv("eucJP", "UTF-8", cgi.params['query']))
cgi.params['query'] = new_query
query_str = cgi.query_string
print "Location: http://marinkyo.que.jp/cgi-bin/sercxo/namazu2.cgi?"+query_str+"\n\n";
稚拙なプログラムではあるが、動けばいいだろうと思い書いたプログラムであったが、動かなかった。 問題はcgi.params['query'] = new_query の部分であり、cgi インスタンスは読み取りしかできず、 更新はできないのである。 実は上のプログラムは別の意味でも間違っていて、cgi.params['query'] は配列であり、文字列ではない。 だから上記の cgi.params['query'] は cgi.param['query'][0] と変更すべきだが、 更新ができないことには変わりない。
その後試行錯誤を経て ここでは言えないぐらい恥ずかしいことを行い、たどり着いたのが次のプログラムである。
#!/usr/local/bin/ruby
require 'cgi'
require 'iconv'
cgi = CGI.new
query_str = ""
cgi.params.each{|key, value|
query_str += key + "=" + CGI.escape(Iconv.conv("eucJP", "UTF-8", value[0])) + ";"
}
print "Location: http://marinkyo.que.jp/cgi-bin/sercxo/namazu2.cgi?"+query_str+"\n\n";
それぞれのハッシュに対して UTF-8 を一度 EUC に変換した後、escape して問題ないようにしている。 ( 2009-10-28 )
慧眼な読者は、上記のプログラムでも誤っていることがわかるだろう。 その理由は、cgi.params というハッシュの key が配列であるにもかかわらず、 その配列の要素が一個だけという前提に立ったものであるからだ。 CGI では、同じ key に対して複数の value があることを許容する。 従って、Ruby の実装では、cgi.params の value を配列として、 複数の value に対応している。 実は、私も上のプログラムに以上の誤りがあることは承知で載せた。 それは、value が配列であることに対応して作成したプログラムが、 なぜかエラーで異常終了するからだった。そのときは理由がわからず、 とにかく公開しようと焦ったのだった。
その後冷静な目で異常終了するプログラムを見てみると、原因がわかった。 あるべき個所にカッコがなかったのだ。ああ、恥ずかしい。 カッコを付けたら正常に動作した。正しいプログラムを示す。
#!/usr/local/bin/ruby
require 'cgi'
require 'iconv'
cgi = CGI.new
query_str = ""
cgi.params.each{|key, values|
values.each{|a_value|
query_str += key + "=" + CGI.escape(Iconv.conv("eucJP", "UTF-8", a_value)) + ";"
}
}
print "Location: http://marinkyo.que.jp/cgi-bin/sercxo/namazu2.cgi?"+query_str+"\n\n";
配列であることを明確にするため、cgi.params から取り出す要素を values と変更し、 values から更に要素をとる a_value という変数を作った。( 2009-12-06 )
その後しばらくして、また動かなくなってしまった。 CGI のエラーログには次のようにある。
[xxx xxx xx 03:10:38.940477 2017] [cgi:error] [pid 98349] [client xxx.xxx.xxx.xxx:xxxxx] AHxxxxx: \ /xxx/xxx/kernel_require.rb:55:in `require': cannot load such file -- iconv (LoadError): \ /xxx/xxx/xxx/xxx/xxx/xxx/namazu.cgi, referer: http://xxx.jp/xxx/xxx.html [xxx xxx xx 03:10:38.940665 2017] [cgi:error] [pid 98349] [client xxx.xxx.xxx.xxx:xxxxx] AHxxxxx: \ \tfrom /xxx/xxx/kernel_require.rb:55:in `require': \ /xxx/xxx/xxx/xxx/xxx/xxx/namazu.cgi, [xxx xxx xx 03:10:38.940734 2017] [cgi:error] [pid 98349] [client xxx.xxx.xxx.xxx:xxxxx] AHxxxxx: \ \tfrom namazu.cgi:4:in `<main>': \ /xxx/xxx/xxx/xxx/xxx/xxx/namazu.cgi, referer: http://xxx.jp/xxx/xxx.html [xxx xxx xx 03:10:38.942220 2017] [cgi:error] [pid 98349] [client xxx.xxx.xxx.xxx:xxxxx] \ End of script output before headers: namazu.cgi, referer: http://xxx.jp/xxx/xxx.html
iconv というライブラリはないよ、といっている。今まで気が付かなかったのがおまぬけなのだが、 さてどうしよう。iconv は Ruby 2.0.0 dev の時点から利用できなくなっていることを知らなかった。 下記のページに告知がある。
http://magazine.rubyist.net/?0041-200Special-note
今後は String#encode や Encoding::Converter、あるいはどうしても iconv が必要な場合は iconv.gem を用いてください
このようにあるので、String#encode を使うのがよいのだろう。 機械的な書き換えはできるのだろうか。
#!/usr/local/bin/ruby -w
require 'cgi'
cgi = CGI.new
query_str = ""
cgi.params.each{|key, values|
values.each{|a_value|
query_str += key + "=" + CGI.escape(a_value.encode("eucJP", "UTF-8")) + ";"
}
}
print "Location: http://marinkyo.que.jp/cgi-bin/sercxo/namazu2.cgi?"+query_str+"\n\n";
案ずるより生むがやすし。Iconv.conv("eucJP", "UTF-8", a_value) を a_value.encode("eucJP", "UTF-8") に変えればよかった ( 2017-05-04 ) 。
以上の処置を施しても、字上符(ダイアクリティカルマーク)のついた文字は、 検索の対象にできない。 検索対象にはできなくとも、せめて、タイトルや要約文の表示は正しく表示されてほしいのだが、 いくつかの文字は消えたり読めなくなったりしている。 エスペラントの固有の文字 ĈĜĤĴŜŬ ĉĝĥĵŝŭ についてみてみよう。 スカルラッティの部屋というページのエスペラント版を Ĉambro de Scarlatti という名前の表題で作っている (HTML 上は <title> と </title> ではさまれた文字列である)。 かりに、Scarlatti というキーワードで検索した時、 候補としてこのページが提示されたとする。このときのタイトルは、 ambro de Scarlatti となってしまっていて、先頭の Ĉ の文字が消えてしまっている。
他にも、Fauré のアクセステギューの字が表示されないなどの問題がある。
これは Namazu の問題か ntf の問題かはわからない (おそらく前者とみている)。 この脱落を防ぐには、 Namazu のインデックスフォルダの namazu.field.subject を直接変更して、 そのあとで rfnmz indexdirectoryを行うしかない。 そしてこれらの書き換えは、Namazu を通さず別のプログラムで行なわなければならない。
この問題は、アクセント付き記号の処理で述べる。
まりんきょ学問所 > 全文検索システム Namazu > UTF-8 への対応