在JavaScript之前和之后使用Nokogiri和Ruby进行刮擦会更改值

K M*_*lam 5 javascript ruby nokogiri web-scraping

我有一个程序可以从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
Run Code Online (Sandbox Code Playgroud)

这正确地从"CDS索引"表中删除第二列的日期和值,这很好.现在,我想从"债券指数"表中搜索我遇到问题的类似值.

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

values = doc.css('table#BondIndexTable')
puts values
Run Code Online (Sandbox Code Playgroud)

我从Bond Indexes表中得不到任何结果.但是如果我使用的话,我从CDS索引表中获取值:

values = doc.css('table#CdsIndexTable')
puts values
Run Code Online (Sandbox Code Playgroud)

如何从两个表中获取值?

Win*_*zan 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
Run Code Online (Sandbox Code Playgroud)

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


Cas*_*per 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

CDShttps : //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%"]
Run Code Online (Sandbox Code Playgroud)