Я пытаюсь загрузить страницы больше чем на 1 м (URL, заканчивающиеся идентификатором последовательности). Я реализовал вид многоцелевого менеджера загрузок с настраиваемым количеством потоков загрузки и одного потока обработки. Загрузчик загружает файлы в пакетах:
curl = Curl::Easy.new
batch_urls.each { |url_info|
curl.url = url_info[:url]
curl.perform
file = File.new(url_info[:file], "wb")
file << curl.body_str
file.close
# ... some other stuff
}
Я попытался загрузить образец на 8 000 страниц. При использовании кода выше, я добираюсь 1000 за 2 минуты. Когда я пишу все URL в файл и делаю в оболочке:
cat list | xargs curl
Я генерал все 8 000 страниц за две минуты.
Вещь, мне нужна она, чтобы иметь ее в коде Ruby, потому что существует другой контроль и код обработки.
Я попробовал:
Почему снова используется Завихрение:: Легкий медленнее, чем последующая командная строка завихряются вызовы и как я могу сделать ее быстрее? Или что я делаю неправильно?
Я предпочел бы исправлять свой код менеджера загрузок, чем сделать загрузку для этого случая по-другому.
Перед этим я называл командную строку wget, которому я предоставил файл со списком URL. Howerver, не все ошибки были обработаны, также не было возможно указать выходной файл для каждого URL отдельно при использовании списка URL.
Теперь мне кажется, что лучший способ состоял бы в том, чтобы использовать несколько потоков с системным вызовом для 'завихрений' команды. Но почему, когда я могу использовать непосредственно Вихревой в Ruby?
Код для менеджера загрузок здесь, если он мог бы помочь: Менеджер загрузок (я играл с тайм-аутами от не установленного это к различным значениям, это не казалось справкой),
Любые подсказки ценятся.
Это может быть подходящая задача для Typhoeus
Примерно так (непроверено):
require 'typhoeus'
def write_file(filename, data)
file = File.new(filename, "wb")
file.write(data)
file.close
# ... some other stuff
end
hydra = Typhoeus::Hydra.new(:max_concurrency => 20)
batch_urls.each do |url_info|
req = Typhoeus::Request.new(url_info[:url])
req.on_complete do |response|
write_file(url_info[:file], response.body)
end
hydra.queue req
end
hydra.run
Если задуматься, у вас могут возникнуть проблемы с памятью из-за огромных количество файлов. Один из способов предотвратить это - никогда не сохранять данные в переменной, а вместо этого передавать их напрямую в файл. Для этого вы можете использовать em-http-request .
EventMachine.run {
http = EventMachine::HttpRequest.new('http://www.website.com/').get
http.stream { |chunk| print chunk }
# ...
}
Сначала позвольте мне сказать, что я почти ничего не знаю о Ruby.
Я точно знаю, что Ruby - это интерпретируемый язык; неудивительно, что он медленнее, чем сильно оптимизированный код, скомпилированный для конкретной платформы. В каждой файловой операции, вероятно, будут проверки, которых нет у curl
. «Еще кое-что» еще больше замедлит работу.
Вы пробовали профилировать свой код, чтобы увидеть, на что тратится большая часть времени?
Итак, если вы не установите обработчик on_body, то curb буферизует загрузку. Если вы загружаете файлы, вам следует использовать обработчик on_body. Если вы хотите загрузить несколько файлов с помощью Ruby Curl, попробуйте интерфейс Curl :: Multi.download.
require 'rubygems'
require 'curb'
urls_to_download = [
'http://www.google.com/',
'http://www.yahoo.com/',
'http://www.cnn.com/',
'http://www.espn.com/'
]
path_to_files = [
'google.com.html',
'yahoo.com.html',
'cnn.com.html',
'espn.com.html'
]
Curl::Multi.download(urls_to_download, {:follow_location => true}, {}, path_to_files) {|c,p|}
Если вы хотите просто загрузить один файл.
Curl::Easy.download('http://www.yahoo.com/')
Вот хороший ресурс: http://gist.github.com/405779
Стиви,
есть ли вероятность, что Net :: HTTP будет достаточно для простой загрузки HTML-страниц?