OLE::Storage_Lite を用いた SummaryInfomation の取得2006年02月10日 06時41分11秒

現在、OLE::Storage_Lite を用いて OLE の複合ファイルに含まれる SummaryInformation や DocumentSummaryInformation のプロパティ情報を取得するプログラムを Perl で書いています。

これにより、現在 非OLE コントロールフィルタ(および xdoc2txt.plを除く) でプロパティ情報の取得に使用している wvSummary の置き換えが可能となります。

実用上、wvSummary でも十分ですが、外部コマンドであることと、wvWare をインストールする必要があることから、OLE::Storage_Lite で実装できれば手軽に使えるものと思います。

Windows のプログラムであれば、これらのプロパティを取得するのは以前書いた時に比較的簡単に書けた記憶があるのですが、OLE::Storage_Lite を使うと少々面倒でした。(後から OLE::Storage を使うと簡単に取得できることを知りましたが、OLE::Storage をインストールよりは OLE::Storage_Lite を使う方が他のフィルタでも使っているので、都合が良いでしょう。)

さて、現在 SummaryInformation の取得はほぼできていまして、DocumentSummaryInformation の取得を書いています。 ただ、DocumentSummaryInformation のプロパティのうち、

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/the_summary_information_property_set.asp

に載っていないものがあるのですが、これはどこに情報があるのでしょうか???

手元には Property identifier value に 0x00000017, 0x00000013, 0x00000016 を含むファイルがあるのです。

現在の Namazu では DocumentSummaryInformation のプロパティを今のところ使ってはいないのですが、もう少しフィールド情報を増やそうかと思って調べています。 ついでに、UserDefined property も少し調べてみようかと思ってはいますが、UserDefined property のプロパティ名の定義ってどうやっているのだろう。

Spreadsheet::ParseExcel を使った excel フィルタ2006年02月08日 15時13分20秒

Spreadsheet::ParseExcel を使うと Excel の本文テキスト抽出が可能です。
xlhtml の代わりに使うには良いかもしれません。

Excel5, Excel95, Excel97, Excel98 のテキストを統一的に処理するには

$ perl sample/dmpExU.pl CP932 file | nkf -Se

と、しなければなりませんでした。
(UTF-8 や EUC-JP を指定したら文字化け)

$ perl sample/dmpExU.pl CP932 excel5.xls | nkf -Se
=========================================
FILE :/backup/work/HEAD/namazu/tests/data/ja/excel5.xls
COUNT :3
AUTHOR:情報システム部
--------- SHEET:Sheet1
( 0 , 0 ) =>Namazu は手軽に使えることを第一に目指した日本語全文検索システムです。このファイルはテスト用です。
( 2 , 0 ) =>test@namazu.org
--------- SHEET:Sheet2
--------- SHEET:Sheet3

$ perl sample/dmpExU.pl CP932 excel98.xls | nkf -Se
=========================================
FILE :/backup/work/HEAD/namazu/tests/data/ja/excel98.xls
COUNT :3
AUTHOR:乗越洋一
--------- SHEET:Sheet1
( 0 , 0 ) =>Namazu は手軽に使えることを第一に目指した日本語全文検索システムです。このファイルはテスト用です。
( 2 , 0 ) =>test@namazu.org
--------- SHEET:Sheet2
--------- SHEET:Sheet3

十分です。dmpExU.pl を参考にすれば簡単にフィルタは作れるでしょう。


ところで、プロパティの取得はできません(AUTHORのみ可)。
これは xlhtml も同様です。現在は wvWare の wvSummary を使っています。

wvSummary の代わりに OLE::Storage_Lite で実装するのは良いかもしれません。そのものずばりではありませんが、taro7_10.pl には、一太郎のプロパティを取り出す処理が含まれていますので、これを参考にすれば作ることはできるでしょう。

pnamazu から学ぶ - 携帯電話対応 -2006年02月08日 06時12分59秒

perl 版検索クライアント pnamazu には実験的なものではありますが、本家 Namazu にないいくつかの機能があります。

その一つが携帯電話対応です。
今ではフルブラウザ対応の携帯電話もありますし、1ページ当りの容量も昔よりは大きくなっていますが、それでもパソコンのブラウザよりは制限がかかります。

pnamazu では、携帯電話に対応するため、次の拡張が行われています。

A. NMZ.result.* に ${summary::size=XX} とオプションが指定可能
B. user agent が携帯電話のときは、検索文字列を Shift_JIS として扱い、半角カナに対応
C. 携帯電話モード時に、出力するカタカナを X0201 (いわゆる半角カナ)に変換

A は、summary の長さは他のフィールドと同じサイズでデフォルトは200バイト($MAX_FIELD_LENGTH で指定可能)です。
しかし、携帯電話にとっては長すぎるので、サイズを小さくできるようになっています。

pnamazu のサンプルの NMZ.result.phone では、${summary::size=40} が指定されています。


Bは、携帯電話で検索式を入力する際、いわゆる半角カナ (jis x 0201片仮名) が入力に使われることが多いのですが、cgi 内部では、文字コードの自動判別の際にこれを誤ります。

そのため、user agent が携帯電話のときは、文字コードの自動認識を行わず、Shift_JIS に決め打ちで処理するようになっています。


Cは、半角カナに変換することで、出力データのサイズを抑えたり、限られた表示領域を有効に使うのが目的でしょう。

--------------------------------------------------
[本家Namazuへの応用]

A.
本家 Namazu でも、${xxxx} にオプションを指定できるように拡張することを考えています。
その一つに、出力する文字列のサイズを指定できるようにしたいと思います。オプションの形式は pnamazu とは異なるものになるでしょう。

この際にバイト数を指定するのが良いのでしょうが、出力する文字コードによって同じ文字列でもバイト数は異なるのが頭の痛いところです。
(最後にまとめてコード変換をしたいと考えているので....。)

B.
この当時、携帯電話の文字コードは Shift_JIS が一般だったのかもしれませんが、現在は Shift_JIS とは限りません。UTF-8 はもちろん、EUC-JP もありえます。
このため、user agent による文字コードの決め打ちは難しいでしょう。
ただ、user agent で携帯電話であることはわかるので、これで携帯電話モードに切り替えるとかには使えるでしょう。

個人的には半角カナは大嫌いですが、携帯電話という閉じた世界に限るなら半角カナへの対応は考えなければならない問題だろうとは思います。

C.
出力コードが UTF-8 だと半角カナに変換してもサイズは減らないのですが、限られた表示領域により多くの情報を表示するためには半角カナの方が好まれるかもしれません。
同様に全角記号も半角記号に変換した方が良いかもしれません。

SPAMMODE2006年02月01日 02時31分17秒

MHonArc には SPAMMODE があって、宛先を集めることがないように、宛先をマスクする機能があります。

いろいろ細かい設定ができるのですが、
・ ADDRESSMODIFYCODE でヘッダのアドレス部分の変換式が記述でき、
・ MODIFYBODYADDRESSES でADDRESSMODIFYCODEの設定が本文にも有効にできます。

Namazu にも何らかの SPAM 対策をしたいと考えます。

A. インデックス作成時に SPAM 対策を行う
B. namazu, namazu.cgi の出力結果に対して SPAM 対策を行う

のどちらか、あるいは両方の実装が考えられます。
ただし、A の処理を行うと、B の処理は不要ですので、両方実装する場合には、A の処理を行うか、B の処理を行うのか利用者が選択できるというものになるでしょう。

B の処理のみを行う場合は、インデックスに手を加えることなく、SPAM 対策を有効/無効を切り替えられます。
これを利用すると、同じインデックスを用いて、会員のみアクセスできる場所では SPAM 対策をはずし、一般向けでは SPAM 対策を施すといった使い方もできるでしょう。
デメリットは、表示だけの処理のため、検索時にはオリジナルの情報が使用される(結果はもちろんマスクされるが、ヒットするか否かの判定にはオリジナルの情報が使われてしまいます)ということです。

# こう考えると、B の処理だけを実装するのでも十分かもしれません。

対象範囲は、フィールドデータの from と、summary、Message-Id、単語データの NMZ.w やフレーズデータの NMZ.p 辺りになるかと思います。

Bの処理を行うのなら、${xxx} と記述してフィールドデータを使用する際に、オプションで指定できることと、namazurc でも指定できるようになれば良いだろう。

フィールドファイルについて2006年01月14日 13時54分27秒

フィールドデータの from や to, newsgroups, subject などは、複数の文書で同一であることが多々あります。
これをテーブル参照型にすることで、インデックスのサイズを減らすことができるのではないかと思います。

また、フィールド検索は全数チェックなので、テーブル参照型にすることでデータ総数を減らすことができ、高速化が可能ではないかと思います。

現在のフィールドファイルは、文書と1対1対応であり、エディタでの編集が簡単というメリットがあります。
このため、rfnmz の代わりに現在の形式からテーブル参照型に変換するコンバータ、またその逆コンバータがあれば良いでしょう。

フィールドデータは内部的には文字列として扱われています。(ソート時には文字列と、数値の2種類で扱われます。)
これを文字列、数値、日付、etc...等に、より細かく分類することで、より複雑な検索が可能となるでしょう。
たとえば、ある日からある日までの期間検索ができる等です。

テーブルのデータは、データタイプに従ってあらかじめソートしておくと、検索に便利です。

重み付け検索2006年01月11日 13時01分29秒

検索式に重みを指定することで、スコアを操作する検索です。
検索結果をスコア順で表示する場合には、重みを大きくしたものはより上位に表示されます。

例えば検索式が "word1^5 or word2^2"の場合、"word1" の重みが5で "word2"の重みが2となり、"^" は区切り記号となります。

単純な重み付けの実装としては、単語のみに重みの指定ができるものです。

より複雑なものとしては、単語、部分一致検索式、正規表現検索式が考えられます。
フレイズ検索式の場合は、個々の単語に重みを付けることや、フレイズ全体に重みを付けることを検討しなければなりません。

また、グループ検索式にも重みを付けることができても良いでしょう。
フィールド検索式も同様です。
AND,OR,NOT検索は、重み付けされた語を使って演算するだけですので、特に何か特別な処理が必要ということはないでしょう。

注意しなければならないのは、単純な重み付けの実装として、単語のみとした場合でも日本語の場合は、分解してフレイズ検索になることがあることです。
この場合には、分解された個々の単語に指定した同じ重みを付けるのか、
あるいは分解された場合は、指定した重みは無効(重み1)として処理するのかのいづれかを選択しなければならないでしょう。

この例では、重みの区切り記号として "^" を使っていますので、"^" 自体を検索したい場合のことを少し考慮しなければならないということを忘れてはいけません。
Namazu では、"(",")", "{", "}", "\"", "*", "/", "+",":" 等の記号(メタ文字)に特別な意味を持たせていますが、そのほとんどが単語の先頭か末尾といった位置に限られるため、メタ文字のエスケープについてはあまり考えられていません。
メタ文字単体を検索する場合には "^" や {^} といった中身が単一の単語のフレイズ検索の形式で指定する方法があります。(この場合は、単語検索として処理されます。)

ターゲットファイル2005年12月18日 12時55分41秒

mknmz -F オプションで指定するファイルです。
インデックス対象のファイルを1ファイル1行で書いたリストです。
(もしかすると公式な資料にこのファイル形式は載っていないかもしれません。)

path/filename1
path/filename2
path/filename3
:
:

といった感じです。
これを

"path/filename1","メディアタイプ"
"path/filename2","メディアタイプ"
"path/filename3"
:
:

という形式もサポートして、個々のファイルのメディアタイプを直接指定できるように改良したいと思います。
メディアタイプは省略可能で、その場合は通常のメディアタイプの判定を行います。
-t オプションでは個々のファイルのメディアタイプは指定できないためです。

その他にも
・UTF-8コードで記録する。
・空白、ダブルクォーテーション等のエスケープを行う。
・ドライブレター(Windows)
・UNC(Windows)
・パス区切り文字
・大文字/小文字(パス名/Windows)
などのいろいろと考えたいと思います。

NMZ.r について2005年12月18日 12時47分53秒

NMZ.r の形式は変更したい。

・処理しやすい形式に変更する。
(更新、削除、新規登録のチェック等)
・ファイル名はUTF-8で記録する。
・ファイル名に空白等が含まれるものも考慮する。
・メディアタイプを記録して、更新時に利用する。

注意:
・gcnmz等でも利用するので、注意が必要。
(形式を変える前にツール独自の処理ルーチンを廃止し、mknmzと共通のモジュールを使用するように修正が必要)

メディアタイプチェック2005年12月18日 11時49分51秒

mknmzではメディアタイプの判定にFile::MMagicを使っていますが、このメディアタイプの判定に多くの時間がかかっています。

まず、メディアタイプをグループに分けて階層的に判定を行う必要があります。
たとえば、HTMLグループにはMHonArcやPipermail等が含まれ、OLEグループにはWord,Excel,PowerPoint,一太郎文書等、zipグループにはzip,OpenOffice等といったようにグループ分けを行い、最初にどのグループなのかの判定をし次にグループの中のどのタイプなのかを判定するというようにです。
必要なら一番最初にバイナリファイルなのかテキストファイルなのかの判定を行うのが良いかもしれません。ただし、判定にどれくらいコストがかかるのかは見極める必要はあります。

次に判定する順番です。
よく判定するものから優先的に判定し、メディアタイプが判明した時点で判定を終了することで、効率的にチェックが行えます。
HTML,PDF,OLEドキュメント等は比較的よく判定するものですから、これらを優先することで速度は向上するはずです。
(利用用途によってはメールもよく処理するかもしれません。)
ケースバイケースですが、どのようなメディアタイプの文書をどれくらいの割合で処理しているか調査したいものです。

また誤判定を防ぐ意味でも、判定する順番は大切です。
判定材料としての情報が比較的少ないものはできるだけ後で判定しないと誤った結果が得られます。
たとえばMacbinary I が良い例です。

新規登録では仕方ありませんが、更新時は前回判定したメディアタイプのグループを優先的に判定するのが効率的です。
更新時にはメディアタイプが変わっている確率が低いためです。
NMZ.r ファイルにメディアタイプを記録しておき、そのメディアタイプが属するグループの判定をまず行い、違った場合には通常の判定を行います。
この時、グループ内の判定は慎重に行わなければ誤る可能性がありますので、記録されたメディアタイプそのものの判定は避けて、あえてそのグループの判定から行うのが良いだろうと今のところは思っています。

-t オプションで直接メディアタイプを指定することができますが、ここのファイルのメディアタイプを指定することができませんから、-F でファイルリストを指定する場合にも、メディアタイプも指定できるようになっていればこれを使うのも良いでしょう。
ファイルフォーマットは拡張して

"filename","メディアタイプ"

という形式にして、メディアタイプは省略可能。
そして従来の

filename

という形式も互換性のためにサポートしておく。
filename に空白やダブルクォーテーションが含まれる場合についても考慮する必要があるし、UTF-8コードで記録する拡張も合わせて行う。

最後にmknmzの中の判定も比較的複雑なものですから、これも整理したいと考えています。

文書が更新されているかどうかの判定について2005年11月25日 15時40分30秒

mknmz は、文書が更新されているか否かを判断するのにデフォルトではタイムスタンプを用います。

加えて、--check-filesize オプションを用いることで、タイムスタンプが同一であってもファイルサイズが異なるものも文書の中身が更新されたとみなすようにできます。(Namazu 2.0.13 以降)

インデックスは大きくなってしまいますが、これに md5sum や sha1sum 等を用いるのも良いだろうと思います。
md5sum や sha1sum は文書の一部が変更された場合でも値が大きく変化するものですので、文書が修正されたかどうかの判断に用いるのには適しています。(というより、そもそもそういう目的のためのものですし)

ただ、md5sum なら1文書につき128bit=16バイト追加、sha1sum なら160bit=20バイト追加ということですから、文書数が多い場合にはインデックスサイズの増加の影響が大きいかもしれません。(バイナリの場合)

md5sum, sha1sum を使うと、ファイルを移動した文書またはファイル名を変更した文書をうまく取り扱うことができるかもしれません。
もっとも、まったく別の文書であっても md5sum, sha1sum の値が同一になる可能性はあるので、単独で用いるのではなく、md5sum と filesize やタイムスタンプ等と併用する等工夫は必要でしょう。