TracのHyper Estraierプラグインで検索の絞り込みをしたい1

と思って調べてみました。WordやExcelやPDFなどファイルの種類で絞ったり、日時で絞り込みできたら便利だと思うのですが、とてもそこまでのスキルはありません。いろいろと試行錯誤してたぶんできました。。。Tracの日本語情報も最近はあまり出ないので、こんなレベルですが公開してみます(苦笑)。

WordやExcelで絞り込んでみるには一番簡単そうなのが、全文検索する文書データの結果を分けてしまうパターンです。美しくないですが。

makeindex.batでWordやExcelは別にしてみます。estcmd gatherで拡張子ごとに別のフォルダに出しています。

set EXPORT_FOLDER=c:\TracLight\search\repos\SampleProject\rep

set INDEX_FOLDER=c:\TracLight\search\repos\SampleProject\casket
set INDEX_FOLDER_WORD=c:\TracLight\search\repos\SampleProject\casket_word
set INDEX_FOLDER_EXCEL=c:\TracLight\search\repos\SampleProject\casket_excel

set REPOS_URI=file:///C:/TracLight/projects/svn/SampleProject/
rmdir /S /Q %EXPORT_FOLDER%

rmdir /S /Q %INDEX_FOLDER%
rmdir /S /Q %INDEX_FOLDER_WORD%
rmdir /S /Q %INDEX_FOLDER_EXCEL%

svn export %REPOS_URI% %EXPORT_FOLDER%

REM MS-Wordのインデックス
estcmd gather -cl -fx .doc,.docx T@estxfilt -ic CP932 -pc CP932 -cm -sd %INDEX_FOLDER_WORD% %EXPORT_FOLDER%

REM MS-Excelのインデックス
estcmd gather -cl -fx .xls,.xlsx T@estxfilt -ic CP932 -pc CP932 -cm -sd %INDEX_FOLDER_EXCEL% %EXPORT_FOLDER%

estcmd gather -cl -fx .pdf,.rtf,.ppt T@estxfilt -ic CP932 -pc CP932 -cm -sd %INDEX_FOLDER% %EXPORT_FOLDER%

で、Hyper Estraierプラグインはソースを修正しないといけないので、subversionshibuya.tracからチェックアウトします。
searchhyperestraier.pyを修正します。元のSearchHyperEstraierModule(Component)の部分をコピペして、SearchMSWordHyperEstraierModule(Component)とします。修正するのは数か所です。Excelも同様に実施します。

class SearchMSWordHyperEstraierModule(Component):
implements(ISearchSource)

# ISearchProvider methods
def get_search_filters(self, req):
if req.perm.has_permission('BROWSER_VIEW'):
yield ('wordhyperest', u'リポジトリ(Wordのみ)', 1)

def get_search_results(self, req, terms, filters):
if not 'wordhyperest' in filters:
return
#estcmd.exeのパス
estcmd_path = self.env.config.get('searchhyperestraier', 'estcmd_path','estcmd')
#estcmd.exeの引数
estcmd_arg = self.env.config.get('searchhyperestraier', 'estcmd_arg','search -vx -sf -ic Shift_JIS')
estcmd_encode = self.env.config.get('searchhyperestraier', 'estcmd_encode','mbcs')
#Tracのブラウザへのリンクを作るか否か。
#enabled:Tracのブラウザへのリンクを作る
#上記以外:replace_left,url_leftで指定したURLへのリンクを作る
browse_trac = self.env.config.get('searchhyperestraier', 'browse_trac','enabled')

#for multi repos
for option in self.config['searchhyperestraier']:
#リポジトリのパス
if not option.endswith('word.index_path'):
continue
mrepstr = option[:-len('word.index_path')] #'.index_path'の前の文字列がreponame
if RepositoryManager(self.env).get_repository(mrepstr) is None: #mrepstrのrepositoryがない
continue
#インデックスのパス
index_path = self.env.config.get('searchhyperestraier', mrepstr+'word.index_path','')
if index_path == '':#mrepstr+'.index_path'がない
continue
#検索結果のパスの頭で削る文字列
replace_left = self.env.config.get('searchhyperestraier', mrepstr+'word.replace_left','')
if replace_left == '': #mrepstr+'.replace_left'がない
continue
#URLを生成する際に頭につける文字列
#browse_trac=enabledの場合は/がリポジトリのルートになるように
url_left = self.env.config.get('searchhyperestraier', mrepstr+'word.url_left','')
if url_left == '': #mrepstr+'.url_left'がない
continue
if mrepstr != '': #defaultでない
url_left = '/' + mrepstr + url_left

#cmdline = "%s %s %s %s" % (estcmd_path,estcmd_arg,index_path,unicode(query,'utf-8').encode('CP932'))
qline = ' '.join(terms)
cmdline = "%s %s %s %s" % (estcmd_path,estcmd_arg,index_path,qline)
self.log.debug('SearchHyperEstraier:%s' % cmdline)
cmdline = unicode(cmdline).encode(estcmd_encode)
np = NaivePopen(cmdline)
#self.log.debug('Result:%s' % unicode(np.out,'utf-8').encode('mbcs'))
#self.log.debug('Result:%s' % np.out)
if np.errorlevel or np.err:
err = 'Running (%s) failed: %s, %s.' % (cmdline, np.errorlevel,
np.err)
raise Exception, err
if np.out=='': #何も入ってない
continue
dom = parseString(np.out)
root = dom.documentElement
#estresult_node = root.getElementsByTagName("document")[0]
element_array = root.getElementsByTagName("document")
for element in element_array:
#self.log.debug('Result:%s' % 'hoge')
url = ""
title = ""
date = 0
detail = ""
author = "不明"

#detailを生成
elem_array = element.getElementsByTagName("snippet")
detail = self._get_innerText("",elem_array)

#その他の属性を生成
attrelem_array = element.getElementsByTagName("attribute")
for attrelem in attrelem_array:
attr_name = attrelem.getAttribute("name")
attr_value = unicode(attrelem.getAttribute("value"))
#URLとタイトルを生成
#if attr_name == "_lreal": #"_lreal"ではファイル名に' 'などが入っている場合対応できない
# attr_value=attr_value[len(replace_left):].replace("\\","/")
# if browse_trac == "enabled":
# url = self.env.href.browser(url_left + attr_value)
# title = "source:"+ url_left + attr_value
# else:
# url = url_left + attr_value
# title = url_left + attr_value
if attr_name == "_lpath": #s-jisをquoteしたもの("file:///C|/TracLight/…"の形式)
attr_value = urllib.unquote(attr_value).encode('raw_unicode_escape').decode('CP932')
attr_value = attr_value[(len('file:///')+len(replace_left)):]
if browse_trac == "enabled":
url = self.env.href.browser(url_left + attr_value)
title = "source:"+ urllib.unquote(url).encode('raw_unicode_escape').decode('utf-8')
else:
url = url_left + attr_value
title = urllib.unquote(url).encode('raw_unicode_escape').decode('utf-8')
#更新日時を生成
elif attr_name =="@mdate":
date = time.strptime(attr_value,"%Y-%m-%dT%H:%M:%SZ")
self.log.debug('date:%s' % attr_value)
date = to_datetime(datetime.datetime(date[0],date[1],date[2],date[3],date[4],date[5],0,utc)) # for Trac0.11
yield(url,title,date,to_unicode(author,'utf-8'),to_unicode(detail,'utf-8'))
return

#XMLのElementを再帰的に探してテキストを生成
def _get_innerText(self,text,node_array):
for node in node_array:
if node.nodeType == node.TEXT_NODE:
text = text + unicode(node.data).encode('utf-8')
else:
text = self._get_innerText(text,node.childNodes)
return text

trac.iniにも以下のように追記します。word.url_leftは環境に合うように修正が必要です。

word.index_path = C:\TracLight\search\repos\SampleProject\casket_word
word.replace_left = C:\TracLight\search\SampleProject\rep
word.url_left = /

で、プラグインpython setup.py bdist_egg でビルドして、Tracの管理画面からHyper Estraierプラグインをインポートしたら完了です。これで検索画面でWordやExcelチェックボックスがっ表示されるはずです。

Hyper Estraierでは、属性を絞り込んだ検索というのもできるようなので、これもやってみます。