使用 javascript 进行 rvest 网页抓取

Kim*_*Kim 3 html javascript css r rvest

我试图刮掉从日常预测FiveThirtyEight使用rvest,但我感兴趣的对象似乎是一个JavaScript对象,我有困难甚至定位在哪里以及如何寻找。(我不精通 CSS 或 Javascript,尽管我在过去几天尝试自学。)

通过检查网页元素和 CSS 选择器,我发现了以下内容:

  • 要查看的位置是<div id="polling-avg-chart">,所以我尝试了

    library(rvest)
    url <- 
      "https://projects.fivethirtyeight.com/election-2016/national-primary-polls/democratic/"
    
    url %>% 
      read_html() %>% 
      html_nodes("#polling-avg-chart")
    
    Run Code Online (Sandbox Code Playgroud)

    没有太大的成功。输出很简单

    {xml_nodeset (1)}

    [1] <\div id="polling-avg-chart"></div>\n

  • 以点为单位的单个投票结果在 中<g style="clip-path: url("#line-clippoll_avg");"> ... </g>,您可以在其中看到 502 个位置的数字。我猜,我将不得不转换cxcy每个节点到相应的百分比,这是做的<g class="flag-box" transform="translate(30, 161.44093322753096)">...</g>等等。

  • 但是,我没有看到预测线的基础数据,而不是点。

  • 当我将光标悬停在图表上时,我会看到诸如<line class="hover-date-line hide-line">变化之类的事物,以及诸如<path class="link" d="M 0 171.40106812500002 C 15 171.40106812500002 15 170.94093803735575 30 170.94093803735575"></path>变化之类的值,我猜测这些值是创建每日预测线的原因。
  • 但是这些值存储在哪里,以及如何将其转换回“49.1% 克林顿 vs. 26.6% 桑德斯”之类的东西对我来说仍然是个谜。

我看过一些其他职位SO如这个,但他们都不似乎适用于这一特定问题。在整洁的数据框中获得预测百分比的最佳方法是什么?

Aur*_*èle 5

另一种方式是直接抓取资源。

在您的浏览器中,打开开发者工具(F12在 Chrome/Chromium 中),前往“网络”,刷新 ( F5),然后寻找看起来像格式良好的 JSON。找到后,我们复制链接地址(右键单击资源 > 复制链接地址)。

在此处输入图片说明

library(httr)
library(tidyr)
library(purrr)
library(dplyr)
library(ggplot2)

url <- "https://projects.fivethirtyeight.com/election-2016/national-primary-polls/USA.json"

r <- GET(url)
Run Code Online (Sandbox Code Playgroud)

整个数据都在那里。权重也是如此,因此您可能可以重新计算这些平均值。绘制的数据位于"model"

dat <- 
  jsonlite::fromJSON(content(r, as = "text")) %>% 
  map(purrr::pluck, "model") %>% 
  bind_rows(.id = "party") %>% 
  mutate_all(readr::parse_guess)

# # A tibble: 5,288 x 5
#    party candidate_name state forecastdate poll_avg
#    <chr> <chr>          <chr> <date>          <dbl>
#  1 D     Sanders        USA   2016-07-01       36.5
#  2 D     Clinton        USA   2016-07-01       55.4
#  3 D     Sanders        USA   2016-06-30       37.0
#  4 D     Clinton        USA   2016-06-30       54.6
#  5 D     Sanders        USA   2016-06-29       37.0
#  6 D     Clinton        USA   2016-06-29       54.9
#  7 D     Sanders        USA   2016-06-28       37.2
#  8 D     Clinton        USA   2016-06-28       54.4
#  9 D     Sanders        USA   2016-06-27       37.4
# 10 D     Clinton        USA   2016-06-27       53.9
# # ... with 5,278 more rows
Run Code Online (Sandbox Code Playgroud)

重现图表:

dat %>% 
  filter(candidate_name %in% c("Clinton", "Kasich", "Sanders", "Trump")) %>% 
  ggplot(aes(forecastdate, poll_avg)) +
  geom_line(aes(col = candidate_name)) +
  facet_wrap(~party)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

如果你想要互动:

library(dygraphs)
library(htmltools)

foo <- dat %>% 
  filter(candidate_name %in% c("Clinton", "Kasich", "Sanders", "Trump")) %>% 
  split(.$party) %>% 
  map(~ {
    select(.x, forecastdate, candidate_name, poll_avg) %>% 
      spread(candidate_name, poll_avg) %>% 
      {xts(.[-1], .[[1]])} %>%
      dygraph(group = "poll-model") %>% 
      dyRangeSelector()
  })

browsable(tagList(foo))
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明