Как получить динамический контент страницы с капибарой

Попытка получить текст из элементов:

<div class="points-text" data-reactid=".2765swfgy68.1.2.2.1:$sony-xperia-z1-compact.2.0.4.0.0.1">29,367 points</div>

Я предполагаю, что веб-сайты используют Reactjs, а водосвинка не может получить контент даже с драйвером Poltergeist. Есть ли обходной путь?

Вот мой код:

require 'rubygems'
require 'capybara'
require 'capybara/poltergeist'


Capybara.default_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, {js_errors: false})
end


class WebScraper
  include Capybara::DSL

  def get_page_data(url)
    visit(url)
    doc = Nokogiri::HTML(page.html)
    p doc.css('.points-text')
  end
end


scraper = WebScraper.new
puts scraper.get_page_data('http://versus.com/en/sony-xperia-z1-compact')

person ambi    schedule 26.11.2015    source источник


Ответы (2)


Нет необходимости анализировать html с помощью Nokogiri, если вы уже используете Capybara.

def get_page_data(url)
  visit(url)
  p find(:css, '.points-text').text      
end

напечатает видимый текст в элементе с классом points-text

person Thomas Walpole    schedule 26.11.2015
comment
@ambi работал на меня. Я предполагаю, что вы, вероятно, используете phantomjs ‹ 2, который не обеспечивает привязку, поэтому реакция не работает, вы бы увидели это, если бы у вас не было js_errors: false - person Thomas Walpole; 09.12.2015

Этот код работает с selenium и webkit, но НЕ работает с драйвером полтергейст. Из скриншотов видно, что javascript на сайте даже не выполняется.

require 'capybara'
require 'capybara-webkit'
require 'capybara/poltergeist'

Capybara.default_driver = :poltergeist
# Capybara.default_driver = :selenium
# Capybara.default_driver = :webkit
Capybara.register_driver :poltergeist do |app|
  Capybara::Poltergeist::Driver.new(app, {js_errors: false})
end
Capybara::Webkit.configure do |config|
  config.allow_unknown_urls
end


class WebScraper
  include Capybara::DSL

  def get_page_data(url)
    visit(url)

    max_same_times = 3
    same_times = 0
    old_points = nil
    20.times do |i|
      doc = Nokogiri::HTML(page.html)
      # p doc.css('.points-text')
      points = doc.css('.points-text')
      # p [same_times, max_same_times]
      if same_times == max_same_times
        break
      end
      if points.length > 0
        points = points[0].text
        # p [old_points, points]
        if old_points == points
          same_times += 1
        else
          same_times = 0
        end
        old_points = points
      end
      page.save_screenshot("#{i}.png")
    end
    old_points
  end
end


scraper = WebScraper.new
puts scraper.get_page_data('http://versus.com/en/sony-xperia-z1-compact')
person ambi    schedule 09.12.2015
comment
Я не понимаю, почему вы все еще хотите использовать Nokogiri, когда вы уже используете Capybara - это просто пустой анализ html. Вы можете просто сделать points = all(:css, '.points-text') для возврата массива, подобного объекту всех совпадающих элементов на странице, вместо того, чтобы постоянно пересматривать html страницы с помощью Nokogiri. Вы также можете использовать points = all(:css, '.points-text', минимум: 1), если вы хотите, чтобы он ждал отображения хотя бы одного элемента, а затем возвращал все совпадения или только сначала (:css, 'points -text', минимум: 1) чтобы получить первый соответствующий элемент на странице, так как это весь ваш код, кажется, использует - person Thomas Walpole; 14.12.2015