hitode909の日記

趣味はマリンスポーツですの日記です

スクレイピングするクラスのテスト

スクレイピング対象のページが基本的に変更されることのない場合(近デジとか),キャッシュを作っておくと,毎回リクエストを投げずに済んで便利.
GETしか使わないときは簡単にキャッシュできる.


必ずUtil::fetch_uriというメソッドで通信するようにしておいて,

module Util
  def self.fetch_uri(uri)
    uri = URI.parse(uri) unless uri.kind_of? URI
    uri.read
  end
end


spec_helperとかでメソッドを上書きして,キャッシュがあればそっちを使うようにする.

module Util
  def self.fetch_uri(uri)
    uri = URI.parse(uri) unless uri.kind_of? URI

    cache_directory = File.join(File.dirname(__FILE__), '..', 'spec', 'cache')
    Dir.mkdir(cache_directory) unless File.directory?(cache_directory)

    cache_file = File.join(cache_directory, Digest::SHA1.hexdigest(uri.to_s))
    unless File.exists? cache_file
      open(cache_file, 'w') {|f|
        f.puts Marshal.dump(uri.read)
      }
    end

    Marshal.load open(cache_file).read
  end
end


open-uriURI#readの返り値は拡張されていて,base_uriとかが取れるようになってる.
openするとStringIOが来るのでMarshalでdumpできないけど,URI#readするとStringが返ってきてdumpできる.

ruby-1.9.2-p0 > Marshal.dump(open('http://google.com'))
TypeError: no marshal_dump is defined for class StringIO

ruby-1.9.2-p0 > Marshal.load(Marshal.dump(URI.parse('http://google.com').read)).base_uri
=> #<URI::HTTP:0x000001011dc390 URL:http://www.google.co.jp/>


POSTもしたいときはWebMockが使えそう.
POST可能なRubyのNet::HTTP偽装テストライブラリWebMock+ - きたももんががきたん。