2012-02-22 12 views
7

Ho iniziato a conoscere di recente i web crawler e ho creato un crawler di esempio con Ruby, Anemone e Mongodb per l'archiviazione. Sto testando il crawler su un enorme sito Web pubblico con possibilmente miliardi di link.Ruby, Mongodb, Anemone: web crawler con possibili perdite di memoria?

Il crawler.rb sta indicizzando le informazioni corrette, anche se quando controllo l'utilizzo della memoria nel monitor dell'attività mostra che la memoria è in costante aumento. Ho solo eseguito il crawler per circa 6-7 ore e la memoria mostra 1.38 GB per mongod e 1.37 GB per il processo Ruby. Sembra che stia crescendo di circa 100 MB ogni ora o così.

Sembra che io possa avere una perdita di memoria? È il loro modo migliore di ottenere la stessa scansione senza che la memoria diventi fuori controllo in modo che possa funzionare più a lungo?

# 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

Hai trovato la causa della perdita? Se pensi che sia stato un bug in Anemone, lo hai segnalato sul loro [issue tracker] (https://github.com/chriskite/anemone/issues)? –

+0

I problemi correlati menzionati nel tracker dei problemi Anemone includono: [perdita di memoria?] (Https://github.com/chriskite/anemone/issues/49), [perdita di memoria o gestione inefficiente della memoria] (https://github.com/chriskite/anemone/issues/29), e [Risolve errore OutOfMemory per siti di grandi dimensioni] (https://github.com/chriskite/anemone/pull/30) –

+0

L'ho segnalato all'incirca nello stesso tempo di postare qui su SO. Sono stato in grado di eseguire la scansione di ciò che il mio compito richiedeva aggiungendo le correzioni suggerite e ha reso la mia scansione molto più lunga, anche se l'utilizzo della ram era in costante crescita, ma non così velocemente come in precedenza. Non sono ancora sicuro di cosa causa la perdita di memoria. – viotech

risposta

3

Ho anche un problema con questo, ma sto usando redis come archivio dati.

questo è il mio cingolato:

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 

ho applicato la patch dal here al mio file core.rb nella gemma anemone:

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, 

...

(Il seguente era in linea 155)

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

e ho un lavoro cron oraria fare:

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

per cercare di mantenere l'utilizzo della memoria Redis' verso il basso. Sto riavviando una scansione gigante ora, quindi vedremo come va!

Riporto con i risultati ...

1

Sto facendo qualcosa di simile e penso che forse stai solo creando un sacco di dati.

Non si sta salvando il corpo in modo tale da aiutare i requisiti di memoria.

L'unico altro miglioramento che riesco a pensare è utilizzare Redis al posto di Mongo perché ho trovato che era molto più scalabile per l'archiviazione di Anemone.

Controlla la dimensione dei dati che hai in mongo - Ho scoperto che stavo salvando un numero enorme di righe.