w3mでサーチエンジン呼び出し - 一般化編
w3mユーザなら普通 urimethodmap を設定して g:keyword でgoogle検索をやってると思うが、いろんなサーチエンジンで使えるよう一般化してみる。簡単に設定できるようDSLを定義しよう。
defsearch :google, "UTF-8", "http://www.google.com/search?q=%s&hl=ja&num=100" defalias :g, :google
たとえば上のように宣言すると google:keyword や g:keyword で keyword をgoogle検索する。keywordはUTF-8に変換されて%sを置き換える。サーチエンジンの設定で言いたいことはたったこれだけ。ようつべやニコニコ動画やgoogle mapなどにも簡単に対応できる。
さぁ、CGIスクリプトを書こう。俺はw3mのLocal CGIとして使うが、普通のCGIスクリプトなので他のCGI実行環境でも動くはず。*1
#!/usr/bin/env ruby require 'cgi' require 'iconv' CONFIG_FILE = File.expand_path "~/.search-engine.rb" DEFAULT_ENCODING = 'EUC-JP' class SearchEngines def encoding(encoding) @from_encoding = encoding || DEFAULT_ENCODING end def defsearch(name, to_encoding, url_format) (@searches||={})[name.to_s] = lambda {|q| q = Iconv.iconv(to_encoding, @from_encoding, q).first if to_encoding format(url_format, CGI.escape(q)) } end def defalias(alias_, original) @searches[alias_.to_s] = @searches[original.to_s] end def load_config(config_file=CONFIG_FILE) eval(File.read(config_file), binding) end def search(site, query) url = @searches[site][query] print "Location: #{url}\r\n\r\n" end end site, query = CGI.unescape(ENV['QUERY_STRING']).split(/:/, 2) se = SearchEngines.new se.load_config se.search(site, query)
ポイントは設定ファイル ~/.search-engine.rb を SearchEngines オブジェクトのコンテキストでevalしていること。defsearch宣言は、ハッシュ@searchesのエントリに変換される。エントリはlambdaによるクロージャーだ。なのでto_encodingとurl_formatは呼び出し時でも見える。デフォルトエンコーディングはEUC-JPなので、異なる人は変えておこう。
設定ファイルのサンプルをどうぞ。他のサーチエンジンの追加は簡単だ。適当にキーワードを検索して、キーワードの部分を%sに置き換え、「=」でDocument Charsetを調べよう。
# ~/.w3m/urimethodmap への追加を忘れずに # g: file:/cgi-bin/search-engine.cgi?%s # エンコーディングはEUC-JP encoding "EUC-JP" # Google search defsearch :google, "UTF-8", "http://www.google.com/search?q=%s&hl=ja&num=100" defalias :g, :google # Google code search defsearch :gcode, "UTF-8", "http://www.google.com/codesearch?q=%s&hl=ja&num=100" # ようつべ defsearch :youtube, "UTF-8", "http://www.youtube.com/results?search_query=%s&search_type=search_videos&search_sort=relevance" # Google map defsearch :map, "Shift_JIS", "http://maps.google.co.jp/maps?f=q&hl=ja&q=%s&output=html" # ニコニコ動画検索 defsearch :nico, "UTF-8", "http://socia.lix.jp/lab/nicosearch/?key=%s" # 価格.com defsearch :kakaku, "Shift_JIS", "http://kakaku.com/ksearch/search.asp?Query=%s"
最後に ~/.w3m/urimethodmap に以下を追加することを忘れずに。
g: file:/cgi-bin/search-engine.cgi?%s google: file:/cgi-bin/search-engine.cgi?%s youtube: file:/cgi-bin/search-engine.cgi?%s map: file:/cgi-bin/search-engine.cgi?%s nico: file:/cgi-bin/search-engine.cgi?%s kakaku: file:/cgi-bin/search-engine.cgi?%s gcode: file:/cgi-bin/search-engine.cgi?%s
今思ったんだが、urimethodmapに指定されてないschemeなURIをリクエストしたら、Unknown URIと怒るのではなくてLocal CGIを呼び出せればいいなと思った…Rubyにmethod_missingがあるように。
*1:セキュリティは考えていないのでローカルにサーバを立てよう。