如何使用Nokogiri和Ruby从具有隐藏元素的动态折叠表中提取数据

问题描述 投票:0回答:3

我正在尝试通过以下网站抓取:https://www.cdc.gov/coronavirus/2019-ncov/cases-updates/cases-in-us.html

获取有关冠状病毒的所有状态统计信息。

下面的我的代码有效:

require 'nokogiri'
require 'open-uri'
require 'HTTParty'
require 'pry'

  url = https://www.cdc.gov/coronavirus/2019-ncov/cases-updates/cases-in-us.html
  doc = Nokogiri::HTML.parse(open(url))
  total_cases = doc.css("span.count")[0].text
  total_deaths = doc.css("span.count")[1].text
  new_cases = doc.css("span.new-cases")[0].text
  new_deaths = doc.css("span.new-cases")[1].text

但是,我无法进入折叠的数据/网格单元数据。

我尝试按.aria-label类和.rt-tr-group类进行搜索。任何帮助,将不胜感激。谢谢。

ruby web-scraping nokogiri httparty open-uri
3个回答
0
投票

该页面正在使用AJAX加载其数据。

在这种情况下,您可以使用Watir通过浏览器获取页面

如此处回答:https://stackoverflow.com/a/13792540/2784833

另一种方法是直接从API获取数据。

您可以通过查看浏览器控制台上的网络选项卡来查看其他端点


0
投票

我复制了您的代码,发现您可能已经做过的一些错误

require 'HTTParty'

将不起作用。您需要使用

require 'httparty'

第二,变量url值即应该有引号。>

url = "https://www.cdc.gov/coronavirus/2019-ncov/cases-updates/cases-in-us.html"

除此之外,它对我来说还不错。

此外,如果您尝试获取Covid-19数据,则可能要使用这些API

For US CountFor US Daily CountFor US Count - States

您可以了解有关API here的更多信息>

尽管answer of Layon Ferreira已经说明了问题,但它没有提供加载数据所需的步骤。

就像链接答案中已经说过的那样,数据是异步加载的。这意味着数据不在初始页面上,而是通过执行代码的JavaScript引擎加载的。

打开浏览器开发工具时,请转到“网络”标签。您可以清除所有请求,然后刷新页面。您将看到所有已提出请求的列表。如果您正在寻找异步加载的数据,那么最有趣的请求通常是类型为“ json”或“ xml”的请求。

浏览请求时,您会发现所需的数据位于:

https://www.cdc.gov/coronavirus/2019-ncov/json/us-cases-map-data.json

screenshot developer tools

因为这是JSON,所以不需要“ nokogiri”来解析它。

require 'httparty'
require 'json'

response = HTTParty.get('https://www.cdc.gov/coronavirus/2019-ncov/json/us-cases-map-data.json')
data = JSON.parse(response.body)

执行上述操作时,您将获得异常:

JSON :: ParserError ...

我不确定为什么,但是由于某种原因,数据提供者在字符串的开头添加了不可传递的字符。

response.body[0]
#=> ""
format '%X', response.body[0].ord
#=> "FEFF"

[查找时似乎是Zero Width No-Break Space字符。

这意味着我们在解析时必须对第一个字符进行切片。

require 'httparty'
require 'json'

response = HTTParty.get('https://www.cdc.gov/coronavirus/2019-ncov/json/us-cases-map-data.json')
data = JSON.parse(response.body[1..-1])
#=> [{"Jurisdiction"=>"Alabama", "Range"=>"10,001 to 20,000", "Cases Reported"=>10145,  ...

以上内容仍会在irb中显示错误。 irb使用inspect方法显示一条语句的返回值。 HTTParty尝试在第一个response.inspect调用中解析正文。

上面的代码在脚本中可以正常工作,因为它不会显示每个执行语句的返回值。

[如果要在irb中使用它,请用begin / end块包装整个内容。这只会显示last语句的返回值。


0
投票

尽管answer of Layon Ferreira已经说明了问题,但它没有提供加载数据所需的步骤。

© www.soinside.com 2019 - 2024. All rights reserved.