【问题标题】:Extract some JSON using Nokogiri使用 Nokogiri 提取一些 JSON
【发布时间】:2012-01-08 01:37:56
【问题描述】:
require 'open-uri'
require 'json'
require 'nokogiri'

doc = Nokogiri::HTML(open("http://www.highcharts.com/demo/"))

puts doc

但是我希望能够从这个网页中提取 json,使用正则表达式似乎不起作用,以及如何通过 XPath 提取 JSON?

【问题讨论】:

  • 您提供的网址中没有任何 JSON 数据。 (有一些 JavaScript 对象字面量,例如 new Highcharts.Chart(...) 的参数,但这些实际上不是 JSON。)是您尝试提取的原始 JavaScript 数据,还是您尝试从某个地方获取一些其他数据? 你真正想要完成什么?

标签: ruby nokogiri open-uri


【解决方案1】:
require 'open-uri'
require 'json'
doc = JSON.parse(open("http://www.highcharts.com/demo/"))

【讨论】:

  • 它不起作用,因为页面有混合内容 - HTML 和 javascript。
  • 顺便说一句,您需要 'open-uri' 并 .read 读取打开的结果,因为它是一个 StringIO 对象。 doc = JSON.parse(open('xxxxx').read))
  • @pguardiario 对不起,我情不自禁,但到底怎么一个问题是错误的?如果问题正如你所说的那样“错误”,那么答案同样没用?
【解决方案2】:

您可以通过以下方式从 URL 访问脚本标签(不引用外部文件):

require 'open-uri'
require 'nokogiri'
doc = Nokogiri.HTML(open('http://www.highcharts.com/demo/'))
inline_script = doc.xpath('//script[not(@src)]')
inline_script.each do |script|
  puts "-"*50, script.text
end

现在您只需要找到您想要的脚本块并仅提取您想要的数据(使用正则表达式)。没有更多细节,很难猜出您想要什么以及依赖什么。

这是一个相当脆弱的正则表达式,它可以找到我猜你正在寻找的东西:

inline = doc.xpath('//script[not(@src)]').map(&:text)
data   = inline.map{ |js| js[/new Highcharts\.Chart\((.+?\})\);/m,1] }.compact[0]
puts data

这就是你得到的结果:

{
  chart: {
    renderTo: 'container',
    defaultSeriesType: 'line',
    marginRight: 130,
    marginBottom: 25
  },
  title: {
    text: 'Monthly Average Temperature',
    x: -20 //center
  },
  subtitle: {
    text: 'Source: WorldClimate.com',
    x: -20
  },
  xAxis: {
    categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 
      'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
  },
  yAxis: {
    title: {
      text: 'Temperature (°C)'
    },
    plotLines: [{
      value: 0,
      width: 1,
      color: '#808080'
    }]
  },
  tooltip: {
    formatter: function() {
                return '<b>'+ this.series.name +'</b><br/>'+
        this.x +': '+ this.y +'°C';
    }
  },
  legend: {
    layout: 'vertical',
    align: 'right',
    verticalAlign: 'top',
    x: -10,
    y: 100,
    borderWidth: 0
  },
  series: [{
    name: 'Tokyo',
    data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
  }, {
    name: 'New York',
    data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
  }, {
    name: 'Berlin',
    data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
  }, {
    name: 'London',
    data: [3.9, 4.2, 5.7, 8.5, 11.9, 15.2, 17.0, 16.6, 14.2, 10.3, 6.6, 4.8]
  }]
}

注意这不是JSON;这是一个字符串,表示带有对象、字符串、数组、数字和函数字面量的 JavaScript 代码。

【讨论】:

  • 感谢您的精彩回答,我实际上是在尝试提取 JavaScript 代码的系列部分,感谢您指出它不是 json。
猜你喜欢
  • 2013-04-13
  • 2021-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多