2006-10-26
SimpleWikipediaAPI を ruby から使う
WikipediaAPI - ウィキペディア情報をサイトで利用できるAPI
Wikipediaの項目をひいて,XML やら JSON で返してくれる素晴らしい API。Perl から使えるライブラリは既にある(YappoLogs: WebService::SimpleAPI::Wikipedia)ので,ruby から使えるようにしてみた。基本的には川o・-・)<2nd life - TDD で作る RakuAPI ライブラリの真似というかコピペというか。元の SimpleWikipediaAPI には色々オプションがあるのですが,とりあえずキーワードだけ与えて検索結果が XML で返るだけです(id:secondlife さんのをソックリ真似したから…)。そんでもって TDD も真似っ子。
# 上の階層の lib ディレクトリをライブラリパスに追加
$LOAD_PATH << File.dirname(__FILE__) + '/../lib'
require 'test/unit'
require 'simple_wikipedia_api'
class SimpleWikipediaAPITest < Test::Unit::TestCase
def setup
@simple_wikipedia = SimpleWikipediaAPI.new({:proxy_host => 'foo', :proxy_port => 8000, :timeout => 10})
end
def test_instance
assert_instance_of SimpleWikipediaAPI, @simple_wikipedia
end
def test_keyword
results = @simple_wikipedia.keyword('YouTube')
assert_instance_of Array, results
results.each do |result|
# 構造体かどうか
assert_kind_of Struct, result
# 構造体メンバーの型チェック
struct_methods_call result, %w(sid length) do |method|
assert_instance_of Fixnum, method
end
struct_methods_call result, %w(language url title body) do |method|
assert_instance_of String, method
end
assert_instance_of Time, result.datetime
# url は http で始まってるかどうか
assert_match /^http/, result.url
end
end
def test_show
@simple_wikipedia.keyword('YouTube').each do |result|
puts result.body.tosjis
end
end
def struct_methods_call(struct, methods)
methods.each do |method|
yield struct.send(method)
end
end
end
id:secondlife さんも絶賛している(川o・-・)<2nd life - ruby のスクレイピングツールキット scrAPI)scrapi を使っています。しかし proxy に対応していなかったので,パッチを当てました。Reader クラスの read_page メソッドに以下のようなコードを追加。
http = Net::HTTP.new(uri.host, uri.port, options[:proxy_host], options[:proxy_port])
Base クラスのオプションの定義も以下のように修正しました。
READER_OPTIONS = [:last_modified, :etag, :redirect_limit, :user_agent, :timeout, :proxy_host, :proxy_port]
これで上記のテストコードが通るようになります。
ruby の実体はこんな感じ。今のところ動いているけど。
require 'kconv'
require 'uri'
require 'scrapi'
class SimpleWikipediaAPI
WIKIPEDIA_API_URI = 'http://wikipedia.simpleapi.net/api'
class SimpleWikipediaScraper < Scraper::Base
elements = %w(language sid url title body length redirect strict datetime)
elements.each {|el| process el, el => :text }
def collect
self.sid = sid.to_i
self.length = length.to_i
self.redirect = (redirect == 1)
self.strict = (strict == 1)
self.datetime = Time.iso8601(datetime)
end
result *elements
end
attr_accessor :options
def initialize(options = {})
@options = {
:parser => :html_parser
}.update options
end
def keyword(keyword)
uri = URI.parse(WIKIPEDIA_API_URI)
uri.query = queryize({:keyword => keyword.toutf8})
Scraper.define do
process 'result', 'results[]' => SimpleWikipediaScraper
result :results
end.scrape(uri, self.options)
end
private
def queryize(hash)
hash.map {|i| i.map {|j| URI.escape j.to_s }.join '=' }.join('&')
end
end
まあ,ほとんど id:seconflife さんのコードのままです。ただ id メソッドって ruby で使われているので,なんか不具合がある気がして sid とか逃げてます。ちゃんとオプションを渡せるようにしなきゃいけないんだけど,きっと誰かがやってくれるだろう。つーかもうやっていると見た。
- 34 http://wikipedia.simpleapi.net/
- 6 http://b.hatena.ne.jp/entry/http://wikipedia.simpleapi.net/
- 6 http://wiki.fdiary.net/tmpruby/?(Rails)capistrano(SwitchTower)
- 5 http://d.hatena.ne.jp/keyworddiary/Ruby
- 5 http://reader.livedoor.com/reader/
- 4 http://ma2.is-a-geek.net:8000/index.html
- 3 http://d.hatena.ne.jp/secondlife/20060922/1158923779
- 3 http://www.google.co.jp/search?sourceid=navclient-ff&ie=UTF-8&rls=GGGL,GGGL:2006-37,GGGL:ja&q=Switchtower
- 2 http://a.hatena.ne.jp/nekop/
- 2 http://a.hatena.ne.jp/yowa/simple


