2012-02-22 18 views
7

Comencé a aprender sobre los rastreadores web recientemente y construí un rastreador de muestra con Ruby, Anemone y Mongodb para el almacenamiento. Estoy probando el rastreador en un sitio web público masivo con posiblemente miles de millones de enlaces.Ruby, Mongodb, Anemone: rastreador web con posible pérdida de memoria?

El crawler.rb está indexando la información correcta, aunque cuando reviso el uso de memoria en el monitor de actividad muestra que la memoria está en constante crecimiento. Solo corrí el rastreador durante 6-7 horas y la memoria muestra 1.38GB para mongod y 1.37GB para el proceso Ruby. Parece crecer alrededor de 100MB cada hora más o menos.

Parece que podría tener una pérdida de memoria? ¿Es su forma más óptima de lograr el mismo rastreo sin que la memoria se escale fuera de control para que pueda funcionar más tiempo?

# Sample web_crawler.rb with Anemone, Mongodb and Ruby. 

require 'anemone' 

# do not store the page's body. 
module Anemone 
    class Page 
    def to_hash 
     {'url' => @url.to_s, 
     'links' => links.map(&:to_s), 
     'code' => @code, 
     'visited' => @visited, 
     'depth' => @depth, 
     'referer' => @referer.to_s, 
     'fetched' => @fetched} 
    end 
    def self.from_hash(hash) 
     page = self.new(URI(hash['url'])) 
     {'@links' => hash['links'].map { |link| URI(link) }, 
     '@code' => hash['code'].to_i, 
     '@visited' => hash['visited'], 
     '@depth' => hash['depth'].to_i, 
     '@referer' => hash['referer'], 
     '@fetched' => hash['fetched'] 
     }.each do |var, value| 
     page.instance_variable_set(var, value) 
     end 
     page 
    end 
    end 
end 


Anemone.crawl("http://www.example.com/", :discard_page_bodies => true, :threads => 1, :obey_robots_txt => true, :user_agent => "Example - Web Crawler", :large_scale_crawl => true) do | anemone | 
    anemone.storage = Anemone::Storage.MongoDB 

    #only crawl pages that contain /example in url 
    anemone.focus_crawl do |page| 
    links = page.links.delete_if do |link| 
     (link.to_s =~ /example/).nil? 
    end 
    end 

    # only process pages in the /example directory 
    anemone.on_pages_like(/example/) do | page | 
    regex = /some type of regex/ 
    example = page.doc.css('#example_div').inner_html.gsub(regex,'') rescue next 

    # Save to text file 
    if !example.nil? and example != "" 
     open('example.txt', 'a') { |f| f.puts "#{example}"} 
    end 
    page.discard_doc! 
    end 
end 
+0

¿Descubrió la causa de la fuga? Si crees que fue un error en Anemone, ¿lo informaste en su [rastreador de problemas] (https://github.com/chriskite/anemone/issues)? –

+0

Los problemas relacionados que se mencionan en el rastreador de problemas de Anemone incluyen: [¿pérdida de memoria?] (Https://github.com/chriskite/anemone/issues/49), [pérdida de memoria o manejo ineficiente de la memoria] (https://github.com/chriskite/anemone/issues/29), y [Soluciona el error de OutOfMemory para sitios grandes] (https://github.com/chriskite/anemone/pull/30) –

+0

Lo informé aproximadamente al mismo tiempo que escribí aquí en SO. Pude rastrear lo que mi tarea requería al agregar las correcciones sugeridas y eso hizo que mi rastreo dure mucho más tiempo, aunque el uso del RAM estaba creciendo constantemente, pero no tan rápido como antes. Todavía no estoy seguro de qué causa la pérdida de memoria. – viotech

Respuesta

3

También estoy teniendo un problema con esto, pero estoy usando redis como almacén de datos.

este es mi rastreador:

require "rubygems" 

require "anemone" 

urls = File.open("urls.csv") 
opts = {discard_page_bodies: true, skip_query_strings: true, depth_limit:2000, read_timeout: 10} 

File.open("results.csv", "a") do |result_file| 

    while row = urls.gets 

    row_ = row.strip.split(',') 
    if row_[1].start_with?("http://") 
     url = row_[1] 
    else 
     url = "http://#{row_[1]}" 
    end 
    Anemone.crawl(url, options = opts) do |anemone| 
     anemone.storage = Anemone::Storage.Redis 
     puts "crawling #{url}"  
     anemone.on_every_page do |page| 

     next if page.body == nil 

     if page.body.downcase.include?("sometext") 
      puts "found one at #{url}"  
      result_file.puts "#{row_[0]},#{row_[1]}" 
      next 

     end # end if 

     end # end on_every_page 

    end # end crawl 

    end # end while 

    # we're done 
    puts "We're done." 

end # end File.open 

He aplicado el parche de here a mi archivo core.rb en la gema anémona:

35  # Prevent page_queue from using excessive RAM. Can indirectly limit ra te of crawling. You'll additionally want to use discard_page_bodies and/or a  non-memory 'storage' option 
36  :max_page_queue_size => 100, 

...

(La siguiente solía estar en la línea 155)

157  page_queue = SizedQueue.new(@opts[:max_page_queue_size]) 

y tengo un trabajo de cron cada hora haciendo:

#!/usr/bin/env python 
import redis 
r = redis.Redis() 
r.flushall() 

para tratar de mantener el uso de memoria Redis' hacia abajo. Estoy reiniciando un rastreo gigante ahora, así que ya veremos cómo funciona.

Informaré con los resultados ...

1

Estoy haciendo algo similar y creo que tal vez solo está creando una gran cantidad de datos.

No está guardando el cuerpo, por lo que debería ayudar con los requisitos de memoria.

La única otra mejora que puedo pensar es usar Redis en lugar de Mongo, ya que me pareció mucho más escalable para el almacenamiento de Anemone.

Comprueba el tamaño de los datos que tienes en mongo: descubrí que estaba guardando una gran cantidad de filas.