【问题标题】:How to scrape data using Ruby which is generated by a Javascript function?如何使用由 Javascript 函数生成的 Ruby 抓取数据?
【发布时间】:2013-11-11 20:30:50
【问题描述】:

我正在尝试从this 页面的最新日期(表格的第一行)抓取数据 URL 链接。表格的内容似乎是由 JavaScript 函数生成的。

我尝试使用 Nokogiri 来获取它,但 Nokogiri 无法抓取 JavaScript。然后,我尝试仅使用 Nokogiri 获取脚本部分:

url = "http://www.sgx.com/wps/portal/sgxweb/home/marketinfo/historical_data/derivatives/daily_data"
doc = Nokogiri::HTML(open(url))
js = doc.css("script").text
puts js

在输出中,我找到了我想要的类名称为sgxTableGrid 的表。但是,问题是JavaScript函数中没有关于数据URL链接的线索,并且一切都是动态生成的。

有人知道解决这个问题的更好方法吗?

【问题讨论】:

  • 您必须以某种方式运行该页面,让它动态生成,然后将 DOM 作为 HTML 以使用 Nokogiri 进行解析。
  • 您还需要另一种技术,例如无头浏览器:phantomjs
  • 祝你好运。要么代码被故意混淆,要么犯下此问题的开发人员头脑非常非常复杂
  • @tihom,因为 Mechanize 的胆量 ARE Nokogiri,Mechanize 对 JavaScript 代码的作用不亚于 Nokogiri。为此,有两种选择,使用 WATIR 驱动的浏览器或 JavaScript 解释器,或者拉入代码并手动跟踪它以找出检索 JSON 的 URL 是如何生成的。

标签: javascript ruby nokogiri scrape


【解决方案1】:

查看该页面的 HTML,该表是由作为 JavaScript 请求结果接收的 JSON 生成的。

您可以通过向后追溯页面的源代码来了解发生了什么。如果您想在他们的 JavaScript 之外检索 JSON,以下是您需要的一些东西,但是仍然需要做一些工作来实际使用它:

  1. 从这段代码开始:

    require 'open-uri'
    require 'nokogiri'
    
    doc = Nokogiri::HTML(open('http://www.sgx.com/wps/portal/sgxweb/home/marketinfo/historical_data/derivatives/daily_data'))
    scripts = doc.css('script').map(&:text)
    
    puts scripts.select{ |s| s['sgxTableGrid'] }
    

    在编辑器中查看文本输出。搜索sgxTableGrid。你会看到这样的一行:

    var tableHeader =  "<table width='100%' class='sgxTableGrid'>"
    

    往下看一点,你会看到:

    var totalRows = data.items.length - 1;
    

    data 来自被调用函数的参数,所以我们从这里开始。

  2. 获取包含函数名称loadGridns_ 的唯一部分并搜索它。每次找到时,查找参数data,然后查看data 的定义位置。如果它被传递到该方法中,则搜索以查看调用它的内容。重复该过程,直到您发现变量没有传递到函数中,此时您将知道您在创建它的方法处。

  3. 我发现自己在一个以loadGridDatans 开头的函数中,它是执行xhrPost 调用以检索URL 的块的一部分。该 URL 是您要查找的目标,因此获取包含函数的名称,并循环访问传入 URL 的调用,就像您在上述步骤中所做的那样。

  4. 该搜索最终出现在如下行:

    var url = viewByDailyns_7_2AA4H0C090FIE0I1OH2JFH20K1_...
    
  5. 此时您可以开始重构您需要的 URL。打开一个 JavaScript 调试器,比如 Firebug,并在该行放置一个断点。重新加载页面,JavaScript 应该在该行停止执行。单步,或设置断点,并观察 url 变量的创建直到它的最终形式。此时,您可以在 OpenURI 中使用一些东西,应该检索您想要的 JSON。

注意,它们的函数名可能是动态生成的;我没有查看,所以尝试使用函数的全名可能会失败。

他们也可能会序列化日期时间戳或使用序列化的会话密钥以使函数名称唯一/更不透明,这样做有多种原因。

尽管拆开这些东西很痛苦,但这也是动态页面如何工作的一个很好的教训。

【讨论】:

    猜你喜欢
    • 2018-07-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    相关资源
    最近更新 更多