如何使用 Nokogiri 和 Ruby 从带有隐藏元素的动态折叠 table 中提取数据
How to extract data from dynamic collapsing table with hidden elements using Nokogiri and Ruby
我正在尝试浏览以下网站:
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
但是,我无法进入折叠的 data/gridcell 数据。
我尝试通过 class .aria-label 和 .rt-tr-group class 进行搜索。任何帮助,将不胜感激。谢谢。
该页面正在使用 AJAX 加载其数据。
在这种情况下,您可以使用 Watir 通过浏览器获取页面
如此处回答:
另一种方法是直接从API获取数据。
您可以通过检查浏览器控制台上的网络选项卡来查看其他端点
我复制了你的代码并发现了你可能犯的一些错误
require 'HTTParty'
将不起作用。你需要使用
require 'httparty'
其次,您的变量 url
值应该有引号,即
url = "https://www.cdc.gov/coronavirus/2019-ncov/cases-updates/cases-in-us.html"
除此之外,它对我来说效果很好。
此外,如果您正在尝试获取 Covid-19 数据,您可能需要使用这些 API
您可以了解有关 API 的更多信息here
虽然 已经指出了问题,但它没有提供加载数据所需的步骤。
就像链接答案中已经说过的那样,数据是异步加载的。这意味着数据不存在于初始页面上,而是通过 JavaScript 引擎执行代码加载。
打开浏览器开发工具后,转到 "Network" 选项卡。您可以清除所有请求,然后刷新页面。您将看到所有请求的列表。如果您正在寻找异步加载的数据,最有趣的请求通常是 "json" 或 "xml".
类型的请求
浏览请求时,您会发现您要查找的数据位于:
https://www.cdc.gov/coronavirus/2019-ncov/json/us-cases-map-data.json
因为这是 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 ...
这似乎是 Byte Order Mark (BOM) 未被 HTTParty 删除的。很可能是因为响应未指定 UTF-8 字符集。
response.body[0]
#=> ""
format '%X', response.body[0].ord
#=> "FEFF"
为了正确处理 BOM Ruby 2.7 添加了 set_encoding_by_bom
method to IO
which is also available on StringIO
.
require 'httparty'
require 'json'
require 'stringio'
response = HTTParty.get('https://www.cdc.gov/coronavirus/2019-ncov/json/us-cases-map-data.json')
body = StringIO.new(response.body)
body.set_encoding_by_bom
data = JSON.parse(body.gets(nil))
#=> [{"Jurisdiction"=>"Alabama", "Range"=>"10,001 to 20,000", "Cases Reported"=>10145, ...
如果您还没有使用 Ruby 2.7,您可以使用替代品来删除 BOM,但是前者可能是更安全的选择:
data = JSON.parse(response.body.force_encoding('utf-8').sub(/\A\xEF\xBB\xBF/, ''))
我正在尝试浏览以下网站: 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
但是,我无法进入折叠的 data/gridcell 数据。
我尝试通过 class .aria-label 和 .rt-tr-group class 进行搜索。任何帮助,将不胜感激。谢谢。
该页面正在使用 AJAX 加载其数据。
在这种情况下,您可以使用 Watir 通过浏览器获取页面
如此处回答:
另一种方法是直接从API获取数据。
您可以通过检查浏览器控制台上的网络选项卡来查看其他端点
我复制了你的代码并发现了你可能犯的一些错误
require 'HTTParty'
将不起作用。你需要使用
require 'httparty'
其次,您的变量 url
值应该有引号,即
url = "https://www.cdc.gov/coronavirus/2019-ncov/cases-updates/cases-in-us.html"
除此之外,它对我来说效果很好。
此外,如果您正在尝试获取 Covid-19 数据,您可能需要使用这些 API
您可以了解有关 API 的更多信息here
虽然
就像链接答案中已经说过的那样,数据是异步加载的。这意味着数据不存在于初始页面上,而是通过 JavaScript 引擎执行代码加载。
打开浏览器开发工具后,转到 "Network" 选项卡。您可以清除所有请求,然后刷新页面。您将看到所有请求的列表。如果您正在寻找异步加载的数据,最有趣的请求通常是 "json" 或 "xml".
类型的请求浏览请求时,您会发现您要查找的数据位于:
https://www.cdc.gov/coronavirus/2019-ncov/json/us-cases-map-data.json
因为这是 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 ...
这似乎是 Byte Order Mark (BOM) 未被 HTTParty 删除的。很可能是因为响应未指定 UTF-8 字符集。
response.body[0]
#=> ""
format '%X', response.body[0].ord
#=> "FEFF"
为了正确处理 BOM Ruby 2.7 添加了 set_encoding_by_bom
method to IO
which is also available on StringIO
.
require 'httparty'
require 'json'
require 'stringio'
response = HTTParty.get('https://www.cdc.gov/coronavirus/2019-ncov/json/us-cases-map-data.json')
body = StringIO.new(response.body)
body.set_encoding_by_bom
data = JSON.parse(body.gets(nil))
#=> [{"Jurisdiction"=>"Alabama", "Range"=>"10,001 to 20,000", "Cases Reported"=>10145, ...
如果您还没有使用 Ruby 2.7,您可以使用替代品来删除 BOM,但是前者可能是更安全的选择:
data = JSON.parse(response.body.force_encoding('utf-8').sub(/\A\xEF\xBB\xBF/, ''))