Я пытаюсь автоматизировать процесс загрузки данных для каждого округа США из 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, но мне интересно, есть ли более простой способ.
Веб-сайт извлекает данные, когда вы загружаете страницу с помощью запросов API. Вы можете просмотреть эти запросы API, открыв инструменты разработчика и просмотрев сетевой трафик. Мы также можем использовать их для извлечения данных.
Вот общий процесс, который я прохожу:
В браузере хром
Я просматривал вкладку ответов, пока не нашел что-то похожее на данные. Оказывается, запросы услужливо помечены как «данные сетки».
Вы можете щелкнуть правой кнопкой мыши по одному из запросов и скопировать его как завиток (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
Я отредактировал ответ, чтобы объяснить весь процесс. Вы просто повторяете процесс для каждого количества дней. Кажется, в конце концов разница будет заключаться в том, что вы замените «reduce»: «cnt_lt_32» на «reduce»: «cnt_gt_105». Информацию о теле запроса можно найти на вкладке полезных данных запроса.
+1 за список запросов :) Просто мой 2c: поскольку javascript для этого конкретного сайта не минимизирован, просмотр источников, проверка инициаторов запросов / стека вызовов и установка точек останова могут дать ценную информацию и ярлыки при построении запросов. Например. get_projected_loca_model_data()
из crt-climate-explorer.nemac.org/vendor/… аккуратно перечисляет все необходимые grid
значения, необходимые для получения соответствующих рядов данных.
Большое вам спасибо за это. Пара дополнительных вопросов: (1) откуда вы узнали, что нужно поставить «cnt_lt_32»? Судя по URL-адресу, я бы подумал, что это будет «days_tmax_lt_32». (2) если бы я хотел загрузить количество дней с максимальным значением выше 105, 100 и т. д., как бы я скорректировал код?