2012-02-22 47 views
7

我最近开始学习网络爬虫,并且用Ruby构建了一个示例爬虫,用于存储的文件是AnemoneMongodb。我正在一个可能有数十亿个链接的大型公共网站上测试爬虫。Ruby,Mongodb,Anemone:可能会发生内存泄漏的Web爬虫?

crawler.rb正在索引正确的信息,虽然当我检查活动监视器中的内存使用情况时,它显示内存不断增长。我只运行了大约6-7个小时的爬虫,内存显示为1.38GB的Mongo和1.37GB的Ruby进程。这似乎每小时增长大约100MB左右。

看来我可能有内存泄漏?他们是一个更优化的方式,我可以实现相同的抓取,而不会使内存升级失控,从而可以运行更长时间?

# 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

你找出泄漏的原因吗?如果你认为它是海葵中的错误,你是否在他们的[问题跟踪器](https://github.com/chriskite/anemone/issues)上报告过它? – 2012-06-21 17:43:45

+0

关于银莲问题跟踪器上提到的相关问题包括:[内存泄漏?](https://github.com/chriskite/anemone/issues/49),[内存泄漏或内存处理效率低下](https://github.com/chriskite/anemone/issues/29)和[修复大型网站的OutOfMemory错误](https://github.com/chriskite/anemone/pull/30) – 2012-06-21 17:44:14

+0

我在SO上发布的同一时间报告了它。我能够通过添加建议的修补程序来抓取我的任务所需的内容,并且它使得我的抓取时间更长,尽管tbh内存使用量稳步增长,但速度并不像以前那么快。我仍然不确定是什么导致了内存泄漏。 – viotech 2012-06-22 02:40:59

回答

3

我也有这个问题,但我使用redis作为数据存储。

这是我的爬虫:

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 

我申请的补丁从here我core.rb文件中的海葵宝石:

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, 

...

(以下用于在线155)

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

和我有一个小时的cron作业做:

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

,要尽力保持Redis的内存使用了。我现在正在重新开始一个巨大的爬行,所以我们会看看它是怎么回事!

我会报告结果...

1

我正在做类似的事情,我想也许你只是创建大量的数据。

你没有保存身体,所以应该帮助记忆的要求。

我能想到的唯一的其他改进是使用Redis代替Mongo,因为我发现它对于Anemone的存储更具可扩展性。

检查您在mongo中的数据大小 - 我发现我保存了大量的行。