我有什么选择缓存提取的网页?

时间:2013-02-10 18:13:57

标签: ruby http postgresql caching mechanize

我的应用会进行大量的页面抓取,例如获取历史天气数据。一旦我获取了一个特定的页面,我想将它缓存在我的PostgreSQL数据库中,这样我就不必为了那个特定的请求而再次点击远程服务器。

由于历史数据永远不会改变,我想“永远”地缓存它们 - 这需要将缓存的页面存储在长期持久存储中,例如一个数据库。

我编写了一个包含Mechanize的基本缓存机制。它有效,但似乎有一个比我更好的编码排序的人已经实现了这个。

是否有任何宝石或图书馆已经这样做了?

4 个答案:

答案 0 :(得分:1)

所以我想过,我已经想过了,看了一下Mechanize和VCR的源代码,我认为我真的只是过度思考这个问题了。以下工作对我的需求很好。 (我正在使用DataMapper,但将其转换为ActiveRecord模型会很简单):

class WebCache
  include DataMapper::Resource

  property :id, Serial
  property :serialized_key, Text
  property :serialized_value, Text
  property :created_at, DateTime
  property :updated_at, DateTime

  def with_db_cache(akey)
    serialized_key = YAML.dump(akey)
    if (r = self.all(:serialized_key => serialized_key)).count != 0
      # cache hit: return the de-serialized value
      YAML.load(r.first.serialized_value)
    else
      # cache miss: evaluate the block, serialize and cache the result
      yield(akey).tap {|avalue| 
        self.create(:serialized_key => serialized_key, 
                    :serialized_value => YAML.dump(avalue))
      }
    end
  end
end

使用示例:

def fetch(uri)
  WebCache.with_db_cache(uri) {|uri| 
    # arrive here only on cache miss
    Net::HTTP.get_response(URI(uri))
  }
end

评论

我以前认为适当的网络缓存方案会观察和尊重标题字段,如Cache-Control,If-Modified-Since等,以及自动处理超时和其他网络病理。但是对实际网页的检查清楚地表明,真正的静态数据经常被标记为缓存时间短。因此,让调用者决定缓存某些内容以及何时应该重试失败的查询更有意义。

此时,代码变得非常简单。

道德:不要过度思考你的问题。

答案 1 :(得分:0)

VCR可能就是你想要的。

答案 2 :(得分:0)

也许您应该使用代理缓存,例如squid。它比自己尝试更快,更容易,更可靠。

答案 3 :(得分:0)

您可以查看Open-URI-CacheFaraday-HTTP-Cache。第一个可能更接近你需要的东西。既不记录到数据库,也可能编写自己的存储层。我没有使用Heroku的经验,但文件系统似乎是这种缓存的正确位置。