掲示板に検索機能をつける:3. 独自フィルタを作成する
Hyper Estraierでは、そのままでは掲示板のデーターを読ませることができませんので、読ませるためにフィルターを作成します。
掲示板のデーター・フォーマット
私が使っている掲示板スクリプトのデーター・フォーマットは次のようになっています。
ハンドル名<>メールアドレス<>投稿日<>本文<>スレッドタイトル ハンドル名<>メールアドレス<>投稿日<>本文<> ハンドル名<>メールアドレス<>投稿日<>本文<>
1スレッド1ファイルで、1つのレスが1行に格納されています。ハンドル名などが“<>”という文字で区切られていて、最初の行にだけスレッドタイトルが格納されています。改行はHTMLの“br”タグになっています。その他にもHTMLのタグが入っている可能性があります。なお、キャップ(トリップ)がついている場合には、ハンドル名部分が次のようになります。
ハンドル名 </b>キャップ<b><>メールアドレス<>投稿日<>本文<>
たとえば、次のようなスレッドを考えてみます。
ゲームの話しよう 1 名前:よくある名無しさん [sage] 投稿日:2009/07/08(水) 01:22:33 ゲームの話しようぜ! 2 名前:よくある名無しさん [] 投稿日:2009/07/08(水) 08:17:28 しようしよう 3 名前:RPG名無しさん [sage] 投稿日:2009/07/10(水) 21:45:16 ゲームって面白いよね。 最近ドラクエやってる。
このスレッドのデーターは次のように格納されています。
よくある名無しさん<>sage<>2009/07/08(水) 01:22:33<>ゲームの話しようぜ!<>ゲームの話しよう よくある名無しさん<><>2009/07/08(水) 08:17:28<>しようしよう<> RPG名無しさん<>sage<>2009/07/10(水) 21:45:16<>ゲームって面白いよね。<br>最近ドラクエやってる。<>
Hyper Estraierで読み込めるようにするためのフィルタ
Hyper Estraierが扱える文書フォーマットは次の4種類です。
- プレーンテキスト
- HTML
- MIME(電子メール)
- 文書ドラフト
他のデーター形式の場合、上記のどれかの形式に変換することで、Hyper Estraierで扱えるようになります。変換するプログラムを「フィルタ」と呼びます。
Hyper Estraierに付属のフィルタは、インストールしたディレクトリ(私の場合は$HOME)のshare/hyperestraier/filterの下に“estfx〜”という名前で格納されています。私の環境には次のフィルタがインストールされていました。
フィルタ名 | 変換内容 |
---|---|
estfxasis | 何もしない(as is) |
estfxmantotxt | man page → プレーンテキスト |
estfxmsotohtml | Word/Excel/PowerPoint → HTML |
estfxpdftohtml | PDF → HTML |
estfxxdwtotxt | DocuWorks → プレーンテキスト |
これらは引数を1つまたは2つとるコマンドです。最初の引数は入力ファイル名、2つ目の引数は出力ファイル名になります。出力ファイル名が指定されない場合には、標準出力に出力します。
独自フィルタを作成する
以上をふまえ、掲示板データーを変換するフィルタを作成しました。データーにはHTMLのタグが入っているため、HTML形式に変換することにします。名前は「estfxbbstohtml」にしました。ファイルのエンコーディングはUTF8Nにしています。
#!/usr/bin/env ruby $KCODE = 'u' require 'kconv' def main case ARGV.length when 0 $stderr.puts "usage: estfxbbstohtml infile [outfile]" exit when 1 outfile = $stdout else outfile = open(ARGV[1], 'w') end open(ARGV[0]) do |file| resnum = 1 while line = file.gets line = Kconv.toutf8(line) output_header(outfile, get_thread_title(line)) if resnum == 1 outfile.print(get_formatted_res(resnum, line)) resnum += 1 end output_footer(outfile) end outfile.close end def output_header(outfile, title) outfile.print(<<EOS) <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>#{title}</title> </head> <body> EOS end def output_footer(outfile) outfile.print("</body></html>\n") end def get_thread_title(line) if line =~ /^.*<>.*<>.*<>.*<>(.+)$/ $1 else '(タイトル不明)' end end def get_formatted_res(resnum, line) line.gsub!('<b>', '') line.gsub!('</b>', '') if line =~ /^(.*)<>(.*)<>(.*)<>(.*)<>.*$/ handle = $1 mailaddr = $2 date = $3 content = $4 "<p>#{resnum} 名前:#{handle} [#{mailaddr}] #{date}<br>#{content}</p>\n" end end main
一応、中身を説明します。
mainメソッド:はじめに呼び出される処理です。引数の数を判別し、0個なら使い方を表示し、2個なら出力ファイルをオープンします。次に入力ファイルから1行ずつ読んだデーターを加工し、出力します。
output_headerメソッド:HTMLのヘッダーを出力します。指定されたタイトルを“
output_footerメソッド:HTMLのフッターを出力します。
get_thread_titleメソッド:与えられた1つのレス・データーに含まれるスレッドタイトルを返します。スレッドタイトルが取得できなかった場合には「(タイトル不明)」を返します。
get_formatted_resメソッド:与えられた1つのレス・データーを加工し、HTMLの“p”タグで囲まれた段落として返します。
フィルターの出力
上記の「ゲームの話しよう」のスレッド・データーを読み込ませると、次のように出力します。
<html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>ゲームの話しよう</title> </head> <body> <p>1 名前:よくある名無しさん [sage] 2009/07/08(水) 01:22:33<br>ゲームの話しようぜ!</p> <p>2 名前:よくある名無しさん [] 2009/07/08(水) 08:17:28<br>しようしよう</p> <p>3 名前:RPG名無しさん [sage] 2009/07/10(水) 21:45:16<br>ゲームって面白いよね。<br>最近ドラクエやってる。</p> </body></html>
これで独自フィルターが完成しました。