キャッシュ対応のWikiquote
Wikiquoteから1つ引っ張ってきて表示するスクリプトを書き換えた。毎回ネットワークにアクセスするのもバカらしいので、1度に持ってこれる5、6個の引用(HTMLで1枚分)を~/.quotesに保存するようにした。このファイルに引用が存在する限り、ネットワークに見に行くことなく、即座に引用を表示する。.quotesの残りが4個以下になると、とりあえず1つ引用を表示した後にネットワークに追加分の引用を取りにいく。
もしかして、この程度のものでもSQLiteとか使うべきなのかと思った。性能的な問題よりも、実装者のスキルセットの蓄積や使いまわしまで考えると、SQLiteとか良さそう。
最近、Android端末を手に入れたので、モバイル端末でWikiquoteを表示するプログラムでも作ってみようかと思っている。端末を左右にふると、おみくじのようにランダムに引用を表示する。で、実はWikiquote自体へのリンクのほかにもAmazonへのリンクを埋め込んでおいて、その発言をした人に関する本がすぐに買えるようにしておく。で、アフィリエイトでうはうは……うは。
#!/usr/local/bin/ruby require 'open-uri' require 'hpricot' require 'fileutils' QUOTE_FILE = File.expand_path("~/.quotes") class Wikiquote attr_accessor :q def initialize @q = [] end def show cache if @q.size == 0 puts @q.shift cache end def cache if @q.size <= 4 @q += get_quote(fortune) end end def load if(File.exists?(QUOTE_FILE)) @q += File.new(QUOTE_FILE).read.split("\n@@\n") end end def store File.open(QUOTE_FILE, "w") do |f| f.write(@q.join("\n@@\n")) end end def get_quote(date) q = [] doc = Hpricot(open("http://en.wikiquote.org/wiki/#{date}")) doc.search("dl").each do |dl| dd = dl.search("dd") dd.search("ul").remove q << dd.inner_html.strip.gsub(/<[^>]+>/,"").gsub("~","---") end q.delete("") # for some reasons... q.pop; q # so as not to output whitespace end def fortune srand months = %w(January February March April May June July August September October November December) months.shuffle.pop + "_" + (rand(28).to_i + 1).to_s end end if $0 == __FILE__ w = Wikiquote.new w.load w.cache w.show w.store end
しかし、これ、どうしてもネットワークを見に行くときにはコマンドラインに戻ってくるのに時間がかかる。本当はキャッシュに読み込む動作と表示系は非同期的にするのが吉。そうするとこのRubyスクリプトをベースに実行スクリプトを2つ用意して、「$ cache & show」と並列に実行すべきじゃないかと思った。