Кто-нибудь знает плагин для кеширования Ruby Mechanize? - PullRequest
3 голосов
/ 11 апреля 2011

У меня есть скрипт Ruby на механизированной основе для очистки сайта.Я надеюсь ускорить его, кэшируя загруженные HTML-страницы локально, чтобы ускорить весь цикл «настройка вывода -> запуск -> настройка вывода».Я бы предпочел не устанавливать внешний кеш на машину только для этого скрипта.Идеальным решением будет плагин для механизации и прозрачного кэширования извлеченных страниц, изображений и т. Д.

Кто-нибудь знает библиотеку, которая будет это делать?Или другой способ достижения того же результата (второй сценарий выполняется намного быстрее)?

Ответы [ 4 ]

8 голосов
/ 24 августа 2013

Хороший способ сделать это - использовать (AWESOME) VCR gem .

Вот пример того, как вы это сделаете:

require 'vcr'
require 'mechanize'

# Setup VCR's configs.  The cassette library directory is where 
# all of your "recordings" are saved as YAML files.  
VCR.configure do |c|
  c.cassette_library_dir = 'vcr_cassettes'
  c.hook_into :webmock
end

# Make a request...
# The first time you do this it will actually make the call out
# Subsequent calls will read the cassette file instead of hitting the network
VCR.use_cassette('google_homepage') do
  a = Mechanize.new
  a.get('http://google.com/')
end

Как видите ... Видеомагнитофон записывает сообщение в виде файла YAML при первом запуске:

mario$  find tester -mindepth 1 -maxdepth 3
tester/vcr_cassettes
tester/vcr_cassettes/google_homepage.yml

Если вы хотите, чтобы видеомагнитофон создавал новые версии кассет, просто удалите соответствующий файл.

2 голосов
/ 19 октября 2013

Если вы сохраняете некоторую информацию о странице после первого запроса, вы можете перестроить страницу позже без необходимости повторного запроса с сервера.

# 1) store the page information
# uri: a URI instance
# response: a hash of response headers
# body: a string
# code: the HTTP response code
page = agent.get(url)
uri, response, body, code = [page.uri, page.response, page.body, page.code]

# 2) rebuild the page, given the stored information
page = Mechanize::Page.new(uri, response, body, code, agent)

Я использовал эту технику в пауках/ Скреперы, так что код может быть изменен без необходимости повторного запроса всех страниц.Например:

# agent: a Mechanize instance
# storage: must respond to [] and []=, and must accept and return arbitrary ruby objects.
#    for in-memory storage, you could use a Hash.
#    or, you could write something that is backed by a filesystem, mongodb, riak, redis, s3, etc...
# logger: a Logger instance
class Foobar < Struct.new(:agent, :storage, :logger)

  def get_cached(uri)
    cache_key = "_cache/#{uri}"

    if args = storage[cache_key]
      logger.debug("getting (cached) #{uri}")
      uri, response, body, code = args
      page = Mechanize::Page.new(uri, response, body, code, agent)
      agent.send(:add_to_history, page)
      page

    else
      logger.debug("getting (UNCACHED) #{uri}")
      page = agent.get(uri)
      storage[cache_key] = [page.uri, page.response, page.body, page.code]
      page

    end
  end

end

Что вы могли бы использовать следующим образом:

require 'logger'
require 'pp'
require 'rubygems'
require 'mechanize'

storage = {}

foo = Foobar.new(Mechanize.new, storage, Logger.new(STDOUT))
foo.get_cached("http://ifconfig.me/ua")
foo.get_cached("http://ifconfig.me/ua")
foo.get_cached("http://ifconfig.me/ua")
foo.get_cached("http://ifconfig.me/encoding")
foo.get_cached("http://ifconfig.me/encoding")

pp storage

Который печатает следующую информацию:

D, [2013-10-19T14:13:32.019291 #18107] DEBUG -- : getting (UNCACHED) http://ifconfig.me/ua
D, [2013-10-19T14:13:36.375649 #18107] DEBUG -- : getting (cached) http://ifconfig.me/ua
D, [2013-10-19T14:13:36.376822 #18107] DEBUG -- : getting (cached) http://ifconfig.me/ua
D, [2013-10-19T14:13:36.376910 #18107] DEBUG -- : getting (UNCACHED) http://ifconfig.me/encoding
D, [2013-10-19T14:13:52.830416 #18107] DEBUG -- : getting (cached) http://ifconfig.me/encoding
{"_cache/http://ifconfig.me/ua"=>
  [#<URI::HTTP:0x007fe4ac94d098 URL:http://ifconfig.me/ua>,
   {"date"=>"Sat, 19 Oct 2013 19:13:33 GMT",
    "server"=>"Apache",
    "vary"=>"Accept-Encoding",
    "content-encoding"=>"gzip",
    "content-length"=>"87",
    "connection"=>"close",
    "content-type"=>"text/plain"},
   "Mechanize/2.7.2 Ruby/2.0.0p247 (http://github.com/sparklemotion/mechanize/)\n",
   "200"],
 "_cache/http://ifconfig.me/encoding"=>
  [#<URI::HTTP:0x007fe4ac99d2a0 URL:http://ifconfig.me/encoding>,
   {"date"=>"Sat, 19 Oct 2013 19:13:48 GMT",
    "server"=>"Apache",
    "vary"=>"Accept-Encoding",
    "content-encoding"=>"gzip",
    "content-length"=>"42",
    "connection"=>"close",
    "content-type"=>"text/plain"},
   "gzip,deflate,identity\n",
   "200"]}
2 голосов
/ 11 апреля 2011

Я не уверен, что кэширование страниц поможет так сильно. Что еще поможет, так это запись ранее посещенных URL, чтобы вы не посещали их повторно. Кэширование страницы является спорным, потому что вы уже должны были получить важную информацию, когда впервые увидели страницу, поэтому все, что вам нужно сделать, - это проверить, видели ли вы ее уже. Если у вас есть, возьмите сводную информацию, которая вас интересует, и манипулируйте ею по мере необходимости.

Я писал аналитические пауки, используя Perl's Mechanize. Ruby's Mechanize основан на этом. Хранение ранее посещенных URL-адресов в виде кэша SOME было полезно, как хеш, но, поскольку приложения зависали или хосты выходили из строя в середине сеанса, все предыдущие результаты будут потеряны. На этом этапе существовала реальная база данных на диске.

Мне нравится Postgres, но даже SQLite - хороший выбор. Независимо от того, что вы используете, получите важную информацию на диске, где он может пережить перезапуск или сбой.

Что-то еще, что я бы порекомендовал, это использовать YAML-файл для конфигурации вашего приложения. Поместите туда каждый параметр, который может быть изменен во время запуска приложения. Затем напишите приложение, чтобы оно периодически проверяло время изменения этого файла и перезагружало его, если оно было изменено. Таким образом, вы можете настроить его поведение во время выполнения на лету. Мне пришлось написать паука, чтобы проанализировать несколько веб-сайтов корпорации Fortune 50 несколько лет назад. Приложение работало в течение трех недель, несмотря на множество различных сайтов, связанных с этой корпорацией, и, поскольку я мог настроить регулярное выражение, используемое для управления тем, какие страницы приложения обрабатывались, я мог точно настроить его, не закрывая это приложение.

1 голос
/ 11 апреля 2011

Как насчет записи страниц в файлы, каждой страницы в отдельном файле и разделения циклов настройки и запуска?

...