有没有可能用Ruby和Nokogiri来插入JavaScript引擎

Is it possible to plug a JavaScript engine with Ruby and Nokogiri?

本文关键字:插入 JavaScript 引擎 Nokogiri 有可能 Ruby      更新时间:2023-09-26

我正在编写一个应用程序来抓取一些网站并从中抓取数据。我用Ruby,Curl和Nokogiri来做这个。在大多数情况下,这很简单,我只需要ping一个URL并解析HTML数据。设置非常好。

然而,在某些情况下,网站会根据用户在某些单选按钮上的输入来检索数据。这会调用一些JavaScript,从服务器获取更多的数据。生成的URL和发布的数据由JavaScript代码确定。

是否可以使用:

  1. 一个JavaScript库以及这个设置,它将能够为我确定执行HTML页面中的JavaScript?

  2. 除了使用不同的库之外,HTML和JS库是否有一些集成或通信方式?例如,如果点击了一个按钮,Nokogiri需要调用JavaScript,然后JavaScript需要更新Nokogiri。

如果我的方法似乎不是最好的,你的建议是用Ruby在网上构建一个爬行器+抓取器。

编辑:看起来第1点可以使用therubyrace,因为它在代码中嵌入了V8引擎,但有没有2的替代方案?

您正在寻找Watir,它运行一个真正的浏览器,允许您在网页上执行您能想到的每一个操作。还有一个类似的项目叫做Selenium。

你甚至可以在linux机器上使用Watir和所谓的"无头"浏览器。

Watir无头示例

假设我们有这个HTML:

<p id="hello">Hello from HTML</p>

和这个Javascript:

document.getElementById('hello').innerHTML = 'Hello from JavaScript';

(演示:http://jsbin.com/ivihur)

并且您希望获得动态插入的文本。首先,您需要一个安装了xvfbfirefox的Linux盒子,例如在Ubuntu do:上

$ apt-get install xvfb firefox

您还需要watir-webdriverheadless宝石,所以也可以安装它们:

$ gem install watir-webdriver headless

然后你可以用这样的东西从页面上读取动态内容:

require 'rubygems'
require 'watir-webdriver'
require 'headless'
headless = Headless.new
headless.start
browser = Watir::Browser.new
browser.goto 'http://jsbin.com/ivihur' # our example
el = browser.element :css => '#hello'
puts el.text
browser.close
headless.destroy

如果一切顺利,这将输出:

Hello from JavaScript

我知道这也在后台运行浏览器,但这是我能想到的解决你问题的最简单的方法。启动浏览器需要相当长的时间,但随后的请求速度相当快。(在我的Rackspace云服务器上,每次请求运行goto并多次获取上面的动态文本大约需要0.5秒)。

来源:http://watirwebdriver.com/headless/

水豚+PhantomJS

我最喜欢的Ruby控制的无头浏览器是PhantomJS。PhantomJS是一款基于WebKit的无头浏览器。它包括Poltergeist,它是Capybara的司机。

总之,堆栈如下所示:

Capybara -> Poltergeist -> PhantomJS -> WebKit

请注意,您可以将PhantomJS直接与硒网络驱动程序一起使用,但Capybara API更好(IMHO)。

作为一个最小的WebKit实现,PhantomJS的启动时间比Chrome或IE等完整浏览器更快

抓取谷歌结果链接的示例代码:

module Test
  class Google
    include Capybara::DSL
    def get_results
      visit('/')
      fill_in "q", :with => "Capybara"
      click_button "Google Search"
      all(:xpath, "//li[@class='g']/h3/a").each { |a| puts a[:href] }
    end
  end
end
scraper = Test::Google.new
scraper.get_results

除了标准的水豚功能外,Poltergeist还可以做一些非常方便的事情:

  • 使用page.evaluate_scriptpage.execute_script注入并运行您自己的javascript
  • page.within_framepage.within_window
  • page.status_codepage.response_headers
  • page.save_screenshot<-当事情出错时,这真的很好
  • page.driver.render_base64(format, options)
  • page.driver.scroll_to(left, top)
  • page.driver.basic_authorize(user, password)
  • element.native.send_keys(*keys)
  • cookie处理
  • 拖放

Poltergeist GitHub页面上列出了这些功能:https://github.com/teampoltergeist/poltergeist.

Celerity

如果你真的想获得尽可能多的性能,并且不介意切换到JRuby,我发现Celerity速度极快。

Celerity是Java的HTMLUnit的包装器。它速度很快,因为HTMLUnit不是一个完整的浏览器,它更像是一个执行JavaScript的模拟器。缺点是,它不支持完整浏览器所支持的所有JavaScript,因此它不会支持大量JS的网站,但它对大多数网站来说已经足够了,而且一直在变得更好。

另一个优点是JRuby的多线程特性。使用Peach(每个并行)gem,您可以并行启动许多浏览器。我过去用过一个测试套件来完成这项工作,大大缩短了完成的时间。事实上,我们使用Celerity+Peach制作了一个负载测试仪,它比典型的JMeter、Grinder、apachebench等复杂得多。它真的可以锻炼我们的网站!