5

我有一个从https://web.apps.markit.com/WMXAXLP?YYY2220_zJkhPN/sWPxwhzYw8K4DcqW07HfIQykbYMaXf8fTzWT6WKnuivTcM0W584u1QRwj刮取价值的程序

我目前的代码是:

doc = Nokogiri::HTML(open(source_url))

puts doc.css('span.indexDate').text
date = doc.css('span.indexDate').text
date = Date.parse(date)
puts date
values = doc.css('table#CdsIndexTable td.col2 span')
puts values

这会正确地从“CDS 索引”表中刮取第二列的日期和值,这很好。现在,我想从我面临问题的“债券指数”表中抓取类似的值。

我可以看到一个 JavaScript 函数在不加载页面且不更改页面 URL 的情况下更改它。这两个表之间的区别在于它们的 ID 不同,这正是应该的。但是,不幸的是,当我尝试:

values = doc.css('table#BondIndexTable')
puts values

我从债券指数表中一无所获。但是如果我使用,我会从 CDS 索引表中获取值:

values = doc.css('table#CdsIndexTable')
puts values

如何从两个表中获取值?

4

3 回答 3

15

您可以使用 Capybara 和 Poltergeist 驱动程序来执行 Javascript 并格式化页面。Poltergeist 是 PhantomJS 无头浏览器的包装器。这是一个如何做到这一点的示例:

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

Capybara.default_driver = :poltergeist
Capybara.run_server = false

module GetPrice
  class WebScraper
    include Capybara::DSL

    def get_page_data(url)
      visit(url)
      doc = Nokogiri::HTML(page.html)
      doc.css('td.col2 span')
    end
  end
end

scraper = GetPrice::WebScraper.new
puts scraper.get_page_data('https://web.apps.markit.com/WMXAXLP?YYY2220_zJkhPN/sWPxwhzYw8K4DcqW07HfIQykbYMaXf8fTzWT6WKnuivTcM0W584u1QRwj').map(&:text).inspect

访问此处查看使用 Amazon.com 的完整示例: https ://github.com/wakproductions/amazon_get_price/blob/master/getprice.rb

于 2013-12-26T20:59:23.990 回答
5

如果您不想使用 PhantomJS,您也可以在 Firefox 或 Chrome 开发工具上使用网络嗅探器,您将看到 HTML 表数据通过 javascript POST 请求返回到服务器。

然后,您无需使用 Nokogiri 打开原始页面 URL,而是从您的 Ruby 脚本运行此 POST 并解析和解释该数据。看起来它只是嵌入了 HTML 的 JSON 数据。您可以提取 HTML 并将其提供给 Nokogiri。

它需要一些额外的侦探工作,但我已经多次使用这种方法处理 JavaScript 网页和抓取。它适用于大多数简单的任务,但需要深入研究页面和网络流量的内部工作原理。

下面是来自 Javascript POST 请求的 JSON 数据示例:

债券
https ://web.apps.markit.com/AppsApi/GetIndexData?indexOrBond=bond&ClientCode=WSJ

CDS
https ://web.apps.markit.com/AppsApi/GetIndexData?indexOrBond=cds&ClientCode=WSJ

这是快速而肮脏的解决方案,只是为了让您有所了解。这将从初始页面获取 cookie 并在请求中使用它来获取 JSON 数据,然后解析 JSON 数据并将提取的 HTML 提供给 Nokogiri:

require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'json'

# Open the initial page to grab the cookie from it
p1 = open('https://web.apps.markit.com/WMXAXLP?YYY2220_zJkhPN/sWPxwhzYw8K4DcqW07HfIQykbYMaXf8fTzWT6WKnuivTcM0W584u1QRwj')

# Save the cookie
cookie = p1.meta['set-cookie'].split('; ',2)[0]

# Open the JSON data page using our cookie we just obtained
p2 = open('https://web.apps.markit.com/AppsApi/GetIndexData?indexOrBond=bond&ClientCode=WSJ',
          'Cookie' => cookie)

# Get the raw JSON
json = p2.read

# Parse it
data = JSON.parse(json)

# Feed the html portion to Nokogiri
doc = Nokogiri.parse(data['html'])

# Extract the values
values = doc.css('td.col2 span')
puts values.map(&:text).inspect

=> ["0.02%", "0.02%", "n.a.", "-0.03%", "0.02%", "0.04%", 
    "0.01%", "0.02%", "0.08%", "-0.01%", "0.03%", "0.01%", "0.05%", "0.04%"]
于 2012-11-13T16:58:28.630 回答
1

PhantomJS是一个带有 JavaScript API 的无头浏览器。由于您需要在正在抓取的页面上运行脚本,因此浏览器会为您执行此操作;PhantomJS 将允许您在脚本执行后操作和抓取页面。

于 2012-11-13T16:34:21.093 回答