2016-06-13 2 views
0

Я строю простой веб-паук, используя Sidekiq и Mechanize.Sidekiq mechanize перезаписанный экземпляр

Когда я запускаю это для одного домена, он работает нормально. Когда я запускаю его для нескольких доменов, он терпит неудачу. Я считаю, что причина в том, что web_page перезаписывается при создании экземпляром другого работника Sidekiq, но я не уверен, что это правда или как его исправить.

# my scrape_search controller's create action searches on google. 
def create 
    @scrape = ScrapeSearch.build(keywords: params[:keywords], profession: params[:profession]) 
    agent = Mechanize.new 
    scrape_search = agent.get('http://google.com/') do |page| 
    search_result = page.form... 
    search_result.css("h3.r").map do |link| 
     result = link.at_css('a')['href'] # Narrowing down to real search results 
     @domain = Domain.new(some params) 
     ScrapeDomainWorker.perform_async(@domain.url, @domain.id, remaining_keywords) 
    end 
    end 
end 

Я создаю работу Sidekiq для каждого домена. Большинство доменов, которые я ищу, должны содержать только несколько страниц, поэтому нет необходимости в подзаголовках на странице.

Это мой рабочий:

class ScrapeDomainWorker 
    include Sidekiq::Worker 
    ... 

    def perform(domain_url, domain_id, keywords) 
    @domain  = Domain.find(domain_id) 
    @domain_link = @domain.protocol + '://' + domain_url 
    @keywords  = keywords 

    # First we scrape the homepage and get the first links 
    @domain.to_parse = ['/'] # to_parse is an array of PATHS to parse for the domain 
    mechanize_path('/') 
    @domain.verified << '/' # verified is an Array field containing valid domain paths 
    get_paths(@web_page) # Now we should have to_scrape populated with homepage links 

    @domain.scraped = 1 # Loop counter 
    while @domain.scraped < 100 
     @domain.to_parse.each do |path| 
     @domain.to_parse.delete(path) 
     @domain.scraped += 1 
     mechanize_path(path) # We create a Nokogiri HTML doc with mechanize for the valid path 
     ... 
     get_paths(@web_page) # Fire this to repopulate to_scrape !!! 
     end 
    end 
    @domain.save 
    end 

    def mechanize_path(path) 
    agent = Mechanize.new 
    begin 
     @web_page = agent.get(@domain_link + path) 
    rescue Exception => e 
     puts "Mechanize Exception for #{path} :: #{e.message}" 
    end 
    end 

    def get_paths(web_page) 
    paths = web_page.links.map {|link| link.href.gsub((@domain.protocol + '://' + @domain.url), "") } ## This works when I scrape a single domain, but fails with ".gsub for nil" when I scrape a few domains. 
    paths.uniq.each do |path| 
     @domain.to_parse << path 
    end 
    end 

end 

Это работает, когда я скрести один домен, но терпит неудачу с .gsub for nil для web_page когда я скрести несколько доменов.

+0

Добро пожаловать в переполнение стека. Пожалуйста, прочитайте «[mcve]». Пожалуйста, уменьшите код до минимума, который воспроизводит проблему. –

ответ

0

Вы можете обернуть ваш код в другом классе, а затем создать и объект этого класса в ваш рабочий:

class ScrapeDomainWrapper 
    def initialize(domain_url, domain_id, keywords) 
    # ... 
    end 

    def mechanize_path(path) 
    # ... 
    end 

    def get_paths(web_page) 
    # ... 
    end 
end 

И ваш рабочий:

class ScrapeDomainWorker 
    include Sidekiq::Worker 

    def perform(domain_url, domain_id, keywords) 
    ScrapeDomainWrapper.new(domain_url, domain_id, keywords) 
    end 
end 

Кроме того, имейте в виду, что Mechanize::Page#links может быть nil.

+0

Я обернул его, как вы предложили. Я также преобразовал все переменные экземпляра в локальные переменные (@web_page стала веб-страницей и т. Д.). Я все еще получаю «неопределенный метод« gsub »для nil: NilClass» для paths = web_page.links.map {| link | link.href.gsub ((@ domain.protocol + ': //' + @ domain.url), "")}. Как ни странно, если я запускаю его соло, он работает отлично. – Ben

+0

Если вы переместили код в другой класс, вам не нужно переименовывать переменные. Пока они не являются переменными класса, но переменными экземпляра, все в порядке. Кроме того, я думаю, что 'Mechanize :: Link # href' может быть' nil' в некоторых случаях. Вы должны это проверить. – Wikiti

+0

Да, я добавил для этого отказоустойчивость. Спасибо за помощь! – Ben