Очистка данных из раскрывающегося меню без URL-адреса

Я пытаюсь автоматизировать процесс загрузки данных для каждого округа США из The Climate Explorer в R. Интересующие меня данные требуют, чтобы пользователь выбрал их из раскрывающегося меню, но я не могу понять, как это сделать. автоматизируйте это немного.

Я написал код для перехода к соответствующим страницам, на которых есть данные, которые я хотел бы загрузить, просто изменив пятизначный код FIPS округа по следующему URL-адресу: https://crt-climate-explorer.nemac. org/climate_graphs/?fips=01003&id=days_tmax_lt_32f&zoom=7#. Например, просто заменив код «01003» другим кодом в цикле.

На этом этапе мне нужно щелкнуть раскрывающееся меню «Загрузки» и выбрать «Projections.csv», что запускает загрузку интересующих меня данных. Я надеялся, что с этим действием будет связан URL-адрес, но когда я щелкаю правой кнопкой мыши кнопку «Projections.csv» и выбираю «Копировать ссылку», ссылка просто отображается как Void(0);. Есть ли другой способ получить доступ к URL-адресу? Или я делаю это неправильно? Похоже, есть несколько сообщений, посвященных использованию RSelenium, но мне интересно, есть ли более простой способ.

Скриншот сайта


59
1

Ответ:

Решено

Веб-сайт извлекает данные, когда вы загружаете страницу с помощью запросов API. Вы можете просмотреть эти запросы API, открыв инструменты разработчика и просмотрев сетевой трафик. Мы также можем использовать их для извлечения данных.

Вот общий процесс, который я прохожу:

В браузере хром

  1. Щелкните правой кнопкой мыши -> Проверить -> щелкните вкладку «Сеть».
  2. Обновить сайт
  3. Вы должны увидеть заполненный сетевой трафик.

Я просматривал вкладку ответов, пока не нашел что-то похожее на данные. Оказывается, запросы услужливо помечены как «данные сетки».

Вы можете щелкнуть правой кнопкой мыши по одному из запросов и скопировать его как завиток (bash). Затем вы можете использовать httr2::curl_translate, чтобы получить код для выполнения этого запроса с помощью httr2. (Примечание: код Curl следует поместить в необработанную строку)

library(httr2)

curl_translate(r"[curl 'https://grid2.rcc-acis.org/GridData' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.9' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Origin: https://crt-climate-explorer.nemac.org' \
  -H 'Referer: https://crt-climate-explorer.nemac.org/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0' \
  -H 'sec-ch-ua: "Chromium";v = "128", "Not;A=Brand";v = "24", "Microsoft Edge";v = "128"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Windows"' \
  --data-raw '{"grid":"loca:allMax:rcp85","sdate":"1950-01-01","edate":"2006-12-31","elems":[{"name":"maxt","interval":"yly","duration":"yly","reduce":"cnt_lt_32","area_reduce":"county_mean"}],"county":"01003"}']")

#> request("https://grid2.rcc-acis.org/GridData") |> 
#>   req_headers(
#>     Accept = "*/*",
#>     `Accept-Language` = "en-US,en;q=0.9",
#>     Origin = "https://crt-climate-explorer.nemac.org",
#>     `User-Agent` = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0",
#>   ) |>
#>   req_body_raw('{"grid":"loca:allMax:rcp85","sdate":"1950-01-01","edate":"2006-12-31","elems":[{"name":"maxt","interval":"yly","duration":"yly","reduce":"cnt_lt_32","area_reduce":"county_mean"}],"county":"01003"}', "application/json") |>
#>  req_perform()

С этого момента речь идет о преобразовании json в таблицу. поскольку меры приходится разбивать на отдельные запросы, это немного раздражает. Но таким образом вы все равно можете изменить округ, чтобы получить данные для любого округа, который вам нужен.

Я также должен упомянуть, что вы, вероятно, сможете добиться этого с помощью Selenium. Как правило, я бы зарезервировал Selenium для веб-сайтов, где нет другого способа получить данные, поскольку загрузка всего веб-сайта требует больше вычислительной мощности как на вашей стороне, так и на том месте, которое вы собираете. Они предоставили вам эти замечательные данные, поэтому постарайтесь быть добрыми.

library(tidyverse)
library(httr2)

get_data <- function(county_fips) {
  measures <- c("loca:allMin:rcp85", "loca:allMax:rcp85", "loca:wMean:rcp85", "loca:allMin:rcp45",  "loca:allMax:rcp45", "loca:wMean:rcp45")
  request_bodies <- str_replace('{"grid":"MEASURES","sdate":"2006-01-01","edate":"2099-12-31","elems":[{"name":"maxt","interval":"yly","duration":"yly","reduce":"cnt_lt_32","area_reduce":"county_mean"}],"county":"FIPS_CODE"}', "MEASURES", measures) %>%
  str_replace("FIPS_CODE", county_fips)


  reqs <- map(
    request_bodies, 
    ~ request("https://grid2.rcc-acis.org/GridData") %>%
      req_body_raw(.x, "application/json")
  )
  
  resps <- reqs %>%
    req_perform_sequential()
  
  resps %>%
    map(resp_body_json) %>%
    map2(measures,
      ~ pluck(.x, "data") %>%
        tibble(body = .) %>%
        unnest_wider(body, names_sep = "_") %>%
        mutate(body_2 = unlist(body_2)) %>%
        set_names(c("Year", .y))
    ) %>%
    reduce(full_join, by = "Year")
}

get_data("01003")

#> # A tibble: 94 × 7
#>    Year  `loca:allMin:rcp85` `loca:allMax:rcp85` `loca:wMean:rcp85`
#>    <chr>               <int>               <dbl>              <dbl>
#>  1 2006                    0                1.33             0.0774
#>  2 2007                    0                1.98             0.112
#>  3 2008                    0                1.26             0.120
#>  4 2009                    0                1.83             0.268
#>  5 2010                    0                1.37             0.111
#>  6 2011                    0                2.32             0.218
#>  7 2012                    0                1.27             0.0884
#>  8 2013                    0                2.08             0.265
#>  9 2014                    0                1.05             0.0968
#> 10 2015                    0                2.98             0.226