Webをぐるぐる回っていると、2chのDatファイルを高速検索するソフトを見つけました。
- Datファイル全文検索ソフト DatE
http://frozenlib.net/DatE/
これを読んでいると、以下の特徴があるようです。
- Hyper Estraierという全文検索エンジンを使って構築している
- ソフト自体は、.NET 3.5のWPFを使って実装しているようです
何の気なしにダウンロードして圧縮ファイルを展開すると、非常に少量のDLLで構成されているのに気付いて興味が沸きました。
一番気になったのが、estraier.dll がエンジン本体っぽくて、「あれ?結構簡単に配布できる仕組みになっているんだな?」と。
この手のソフトって、インストールの手間が非常に面倒だという固定概念が働いていたもので、面白そうだなぁと思った次第です。
○っぱい派としては、まずはPythonから使えるか調べてみた次第で、ぐぐると かなり引っかかる。
- 全文検索システム Hyper Estraier & DesktopHE を使ってみる - 傀儡師の館.Python - 楽天ブログ(Blog)
http://plaza.rakuten.co.jp/kugutsushi/diary/200702200000/ - HyperEstraierをPythonで使う - Solitaire
http://blog.redhawk.jp/2008/10/hyperestraierpython.html - Python : メモ用紙.txt
http://sinensis.plala.jp/mm/2ae6b2733aa1a8283eafe3eabb96f12df3e71f3c/#1287ba145b084bb8383a7bad7f4efc65b540b6d0 - 【IT-rescue】hyperestraier: python native bindingを作ってみた
http://memo.jj-net.jp/228
ただ、Linux派の方が多いようで、Windowsで動かしたよ〜とか書いてらっしゃる方は、ぱっと見、見当たりませんでした。むぅ。
という訳で、Windows環境でPythonバインディングを使えるようにしてみます。
ダウンロード
まずは、Windows版のエンジンをゲットしないといけないので、以下からバイナリを取得します。
- Windows版のバイナリパッケージ
http://hyperestraier.sourceforge.net/win/
次に、言語バインディングのパッケージを取得します。Pythonバインディングの場合は、SWIGバージョンを使うようです。
ビルドの前に(SWIGのセットアップ)
SWIGを入れた事の無い方は、まずはSWIGをセットアップしましょう。
といっても、展開してパスを追加するだけです。
自分がダウンロードしたのは、swigwin-1.3.36.zip で、これを展開してルートのパス位置を追加しました。
例えば、以下のように。
set PATH=C:\tool2\swig\swigwin-1.3.36;%PATH% set PYTHON_INCLUDE=C:\tool2\Python24\include set PYTHON_LIB=C:\tool2\Python24\libs\python24.lib
ビルドへ挑戦
という訳で、自分の場合、以下の2ファイルを取得しました。
- hyperestraier-1.4.10-win32.zip
- hyper_estraier_wrappers-0.0.15.tar.gz
hyperestraier-1.4.10-win32.zip には重要なDLLとEXEがあり、hyper_estraier_wrappers-0.0.15.tar.gz は、ルートに setup.py と SWIG で使われる HyperEstraier.i が転がっています。
READMEを読むと、以下のように入力せよと書いてありますが、これは Linux 向けの説明ですよね。
make python sudo make python-install
次に Makefileを読むと、以下のようにビルドするようです。う〜ん、makeを呼び出さずに直接、ここに書いてあるコマンドを打ち込みますか。
python: clean
$(PYTHON) setup.py build_ext --swig-cpp
$(PYTHON) setup.py build早速、setup.pyを呼び出してみましょう。(Python 2.4で実行しています)
$ cd F:\Wacky\Test\HyperEstraier\hyper_estraier_wrappers-0.0.15 $ python setup.py build_ext --swig-cpp running build_ext building '_HyperEstraier' extension --swig-cpp is deprecated - use --swig-opts=-c++ swigging HyperEstraier.i to HyperEstraier_wrap.cpp C:\tool2\cygwin\bin\swig.exe -python -c++ -o HyperEstraier_wrap.cpp HyperEstraie r.i creating build creating build\temp.win32-2.4 creating build\temp.win32-2.4\Release C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\cl.exe /c /nologo /Ox /MD /W3 /GX /DNDEBUG -IC:\tool2\Python24\include -IC:\tool2\Python24\PC /TpHype rEstraier_wrap.cpp /Fobuild\temp.win32-2.4\Release\HyperEstraier_wrap.obj HyperEstraier_wrap.cpp f:\Wacky\Test\HyperEstraier\hyper_estraier_wrappers-0.0.15\HyperEstraierWrapper. cpp(4) : fatal error C1083: include ファイルを開けません。'estraier.h': No such file or directory error: command '"C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\cl.e xe"' failed with exit status 2
「estraier.h が無いよ!」と言ってます。estraier.h は、hyperestraier-1.4.10-win32.zip の方に転がっていますので、setup.py を少し弄ってパスを追加しましょう。
module1 = Extension(
'_HyperEstraier',
sources = ['HyperEstraier.i'],
libraries = get_libs('estconfig --libs') + ['stdc++'])
↓
module1 = Extension(
'_HyperEstraier',
sources = ['HyperEstraier.i'],
libraries = [],
include_dirs = ['F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier'])
# ↑include_dirsで、estraier.hのある場所を指定している。
# ↑libraries内の estconfig は Windowsには無いツールなので、一旦空欄にしてます。
再度ビルド。
$ cd F:\Wacky\Test\HyperEstraier\hyper_estraier_wrappers-0.0.15 $ python setup.py build_ext --swig-cpp running build_ext building '_HyperEstraier' extension --swig-cpp is deprecated - use --swig-opts=-c++ swigging HyperEstraier.i to HyperEstraier_wrap.cpp C:\tool2\cygwin\bin\swig.exe -python -c++ -o HyperEstraier_wrap.cpp HyperEstraie r.i C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\cl.exe /c /nologo /Ox /MD /W3 /GX /DNDEBUG -IF:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\h yperestraier -IC:\tool2\Python24\include -IC:\tool2\Python24\PC /TpHyperEstraier _wrap.cpp /Fobuild\temp.win32-2.4\Release\HyperEstraier_wrap.obj HyperEstraier_wrap.cpp f:\Wacky\Test\HyperEstraier\hyper_estraier_wrappers-0.0.15\HyperEstraierWrapper. cpp(249) : warning C4800: 'ESTMTDB *' : ブール値を 'true' または 'false' に強制 的に設定します (警告の処理) ... C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:C:\tool2\Python24\libs /LIBPATH:C:\tool2\Python24\PCBu ild /EXPORT:init_HyperEstraier build\temp.win32-2.4\Release\HyperEstraier_wrap.o bj /OUT:build\lib.win32-2.4\_HyperEstraier.pyd /IMPLIB:build\temp.win32-2.4\Rele ase\_HyperEstraier.lib ライブラリ build\temp.win32-2.4\Release\_HyperEstraier.lib とオブジェクト bui ld\temp.win32-2.4\Release\_HyperEstraier.exp を作成中 HyperEstraier_wrap.obj : error LNK2019: 未解決の外部シンボル _est_cond_new が関 数 __wrap_new_Condition で参照されました。 ... error: command '"C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\link .exe"' failed with exit status 1120
おーまいがっ!!
LIBファイルを作ろう
先ほどのエラーメッセージ「未解決の外部シンボル _est_cond_new が関数 __wrap_new_Condition で参照されました。」の外部シンボル est_cond_new ですが、ぐぐると Hyper Estraier の定義関数である事が判ります。
つまり、「ラッパーコードから Hyper Estraier の関数を参照しているけど、リンクに失敗している」訳ですね。
で、暫く ぐぐると 以下の記事が。
- glucose : Hyper EstraierのPythonバインディングのビルド
http://glucose.jp/logs/shn/22
おそらく,HEをWindowsで使うには,必要なDLLが同梱されているバイナリパッケージを使うことになると思う.だが,これには*.libが入っていない為,Pythonバインディングをコンパイルすることが出来ない.なのでdllからlibを作るのが目標
…確かに、両方のアーカイブファイル共、LIBファイルが全く提供されてませんね。(何でだろう?)
LIBファイルが提供されていないなら、自分で作る必要があります。
一般的には、DLLファイルから dumpbin で 外部公開関数を EXPORTS し、これを DEFファイルとして LIBファイルを作るようです。
- VC++でDLLから.libファイルを作成するには?|C++ フリーでぷろぐらみんぐ
http://ameblo.jp/nana-2007-july/entry-10101317623.html
という訳で、以下のように作ります。
1.dumpbinを使って、外部公開関数を EXPORTS します。
$ cd F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier $ dumpbin /exports estraier.dll > estraier.def $ dumpbin /exports regex.dll > regex.def $ dumpbin /exports qdbm.dll > qdbm.def
2.EXPORTSした出力内容を、DEFファイルの形式に修正します。例えば、以下のように。
LIBRARY estraier
EXPORTS
est_accept_conn
est_border_str
est_break_text
est_break_text_chrcat
...3.libを使って、DEFファイルからLIBファイルを生成します。
$ lib /def:estraier.def /MACHINE:x86 /out:estraier.lib Microsoft (R) Library Manager Version 7.10.6030 Copyright (C) Microsoft Corporation. All rights reserved. ライブラリ estraier.lib とオブジェクト estraier.exp を作成中 $ lib /def:regex.def /MACHINE:x86 /out:regex.lib Microsoft (R) Library Manager Version 7.10.6030 Copyright (C) Microsoft Corporation. All rights reserved. ライブラリ regex.lib とオブジェクト regex.exp を作成中 $ lib /def:qdbm.def /MACHINE:x86 /out:qdbm.lib Microsoft (R) Library Manager Version 7.10.6030 Copyright (C) Microsoft Corporation. All rights reserved. ライブラリ qdbm.lib とオブジェクト qdbm.exp を作成中
再度ビルド
作成したLIBファイルを、setup.pyの libraries に含めましょう。
module1 = Extension(
'_HyperEstraier',
sources = ['HyperEstraier.i'],
libraries = [],
include_dirs = ['F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier'])
↓
module1 = Extension(
'_HyperEstraier',
sources = ['HyperEstraier.i'],
libraries = ['estraier','regex', 'qdbm'],
include_dirs = ['F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier'])
それでは再度ビルド。
$ cd F:\Wacky\Test\HyperEstraier\hyper_estraier_wrappers-0.0.15 $ python setup.py build_ext --swig-cpp running build_ext building '_HyperEstraier' extension --swig-cpp is deprecated - use --swig-opts=-c++ swigging HyperEstraier.i to HyperEstraier_wrap.cpp C:\tool2\cygwin\bin\swig.exe -python -c++ -o HyperEstraier_wrap.cpp HyperEstraie r.i C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\cl.exe /c /nologo /Ox /MD /W3 /GX /DNDEBUG -IF:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\h yperestraier -IC:\tool2\Python24\include -IC:\tool2\Python24\PC /TpHyperEstraier _wrap.cpp /Fobuild\temp.win32-2.4\Release\HyperEstraier_wrap.obj HyperEstraier_wrap.cpp ... C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin\link.exe /DLL /nologo /INCREMENTAL:NO /LIBPATH:C:\tool2\Python24\libs /LIBPATH:C:\tool2\Python24\PCBu ild estraier.lib regex.lib qdbm.lib /EXPORT:init_HyperEstraier build\temp.win32- 2.4\Release\HyperEstraier_wrap.obj /OUT:build\lib.win32-2.4\_HyperEstraier.pyd / IMPLIB:build\temp.win32-2.4\Release\_HyperEstraier.lib ライブラリ build\temp.win32-2.4\Release\_HyperEstraier.lib とオブジェクト bui ld\temp.win32-2.4\Release\_HyperEstraier.exp を作成中
お、ビルドできたようです。
では、インストール。
$ cd F:\Wacky\Test\HyperEstraier\hyper_estraier_wrappers-0.0.15 $ python setup.py build running build running build_py copying HyperEstraier.py -> build\lib.win32-2.4 running build_ext $ python setup.py install running install running build running build_py running build_ext running install_lib copying build\lib.win32-2.4\HyperEstraier.py -> C:\tool2\Python24\Lib\site-packa ges copying build\lib.win32-2.4\_HyperEstraier.pyd -> C:\tool2\Python24\Lib\site-pac kages byte-compiling C:\tool2\Python24\Lib\site-packages\HyperEstraier.py to HyperEstr aier.pyc
どうやらインストールは成功した模様です。
使ってみよう
早速使ってみましょう。
まずは、以下を参考に、インデックスを作成してみます。
- ウノウラボ Unoh Labs: Tips for HyperEstraier
http://labs.unoh.net/2008/10/tips_for_hyperestraier.html
え〜と、win版Hyper Estraierのルート(F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier)から doc フォルダに対して作業を掛けてみましょう。
$ cd F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier $ estcmd create idx estcmd: INFO: status: name=idx dnum=0 wnum=0 fsiz=6899176 crnum=0 csiz=0 dknum=0 estcmd: INFO: closing: name=idx dnum=0 wnum=0 fsiz=6899280 crnum=0 csiz=0 dknum= 0 $ estcmd gather idx doc estcmd: INFO: reading list from the directory: doc estcmd: INFO: status: name=idx dnum=0 wnum=0 fsiz=6899280 crnum=0 csiz=0 dknum=0 estcmd: INFO: 1 (F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperest raier\doc\cguide-en.html): registered estcmd: INFO: 2 (F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperest raier\doc\cguide-ja.html): registered ... estcmd: INFO: closing: name=idx dnum=205 wnum=12358 fsiz=7643613 crnum=0 csiz=0 dknum=0 estcmd: INFO: finished successfully: elapsed time: 0h 0m 6s
…インデックスの生成って、結構あっけないもんですね。
気を取り直して、Pythonからインデックスデータを操作してみましょう。
$ cd F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier
$ python
Python 2.4.2 (#67, Sep 28 2005, 12:41:11) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import HyperEstraier
>>> db = HyperEstraier.Database()
>>> db.open("idx", HyperEstraier.Database.DBREADER)
True
>>> cond = HyperEstraier.Condition()
>>> cond.set_phrase("python")
>>> result = db.search(cond, 0)
>>> for id in result:
... doc = db.get_doc(id, 0)
... for attr_name in doc.attr_names():
... print "%s : %s" % (attr_name, doc.attr(attr_name))
...
@author : Mikio Hirabayashi
@digest : f3f401613da4a5b6ee8333fea3bc548f
@id : 3
@lang : en
@size : 8034
@title : Hyper Estraier: a full-text search system for communities
@type : text/html
@uri : file:///F|/Wacky/Test/HyperEstraier/hyperestraier-1.4.10-win32/hyperestra
ier/doc/index.html
_lfile : index.html
_lpath : file:///F|/Wacky/Test/HyperEstraier/hyperestraier-1.4.10-win32/hyperest
raier/doc/index.html
_lreal : F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier\do
c\index.html
author : Mikio Hirabayashi
content-language : en
content-script-type : text/javascript
content-style-type : text/css
content-type : text/html; charset=UTF-8
description : homepage of Hyper Estraier
keywords : Hyper Estraier, Estraier, full-text search, API
@author : Mikio Hirabayashi
@digest : f3f401613da4a5b6ee8333fea3bc548f
@id : 3
@lang : en
@size : 8034
@title : Hyper Estraier: a full-text search system for communities
@type : text/html
@uri : file:///F|/Wacky/Test/HyperEstraier/hyperestraier-1.4.10-win32/hyperestra
ier/doc/index.html
_lfile : index.html
_lpath : file:///F|/Wacky/Test/HyperEstraier/hyperestraier-1.4.10-win32/hyperest
raier/doc/index.html
_lreal : F:\Wacky\Test\HyperEstraier\hyperestraier-1.4.10-win32\hyperestraier\do
c\index.html
author : Mikio Hirabayashi
content-language : en
content-script-type : text/javascript
content-style-type : text/css
content-type : text/html; charset=UTF-8
description : homepage of Hyper Estraier
keywords : Hyper Estraier, Estraier, full-text search, API…えっ?と思う程、簡単に制御できちゃうもんですねぇ。
う〜ん、これを使って何か面白い事できそうかな?