在 R 中下载 API JSON 文件并转换为数据帧

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

我正在尝试从 R 中的纳斯达克请求 URL 中提取 JSON 文件,但没有成功。我已经能够用 Python 制定解决方案,但如果可能的话,我真的很想在 R 中找到解决方案。

我已联系纳斯达克帮助台,但他们不支持通过请求 API URL 访问数据。

我在 Stack Overflow 上看到了几种解决方案,但似乎没有一个适合我的特定情况。这是最简单的尝试和我收到的结果:

library(jsonlite)
data <- fromJSON('https://api.nasdaq.com/api/calendar/dividends?date=2023-10-09')

Error in open.connection(con, "rb") : cannot open the connection
In addition: Warning message:
In open.connection(con, "rb") :
  InternetOpenUrl failed: 'The operation timed out'

我不认为上述尝试是正确的方法,所以我希望有人看到这一点并找到可行的解决方案。

我的预期结果是将从请求 API URL (https://api.nasdaq.com/api/calendar/dividends?date=2023-10-09) 中提取 JSON 文件并转换为 R数据框。

r json url request
1个回答
0
投票

确实,该网站(故意?)挂在一些基于标题的查询上。

TL;博士

library(httr)
url <- 'api.nasdaq.com/api/calendar/dividends?date=2023-10-09'
response <- GET(url, add_headers(
  `User-Agent`= "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0"
  ,`Accept-Language`= "en-US,en;q=0.5"
))
status_code(response)
# [1] 200
str(content(response))
# List of 3
#  $ data   :List of 2
#   ..$ calendar :List of 3
#   .. ..$ asOf   : chr "Mon, Oct 9, 2023"
#   .. ..$ headers:List of 8
#   .. .. ..$ symbol                   : chr "Symbol"
#   .. .. ..$ companyName              : chr "Name"
#   .. .. ..$ dividend_Ex_Date         : chr "Ex-Dividend Date"
#   .. .. ..$ payment_Date             : chr "Payment Date"
#   .. .. ..$ record_Date              : chr "Record Date"
#   .. .. ..$ dividend_Rate            : chr "Dividend"
#   .. .. ..$ indicated_Annual_Dividend: chr "Indicated Annual Dividend"
#   .. .. ..$ announcement_Date        : chr "Announcement Date"
#   .. ..$ rows   :List of 2
#   .. .. ..$ :List of 8
#   .. .. .. ..$ companyName              : chr "Brady Corporation Common Stock"
#   .. .. .. ..$ symbol                   : chr "BRC"
#   .. .. .. ..$ dividend_Ex_Date         : chr "10/09/2023"
#   .. .. .. ..$ payment_Date             : chr "10/31/2023"
#   .. .. .. ..$ record_Date              : chr "10/10/2023"
#   .. .. .. ..$ dividend_Rate            : num 0.235
#   .. .. .. ..$ indicated_Annual_Dividend: num 0.94
#   .. .. .. ..$ announcement_Date        : chr "9/04/2023"
#   .. .. ..$ :List of 8
#   .. .. .. ..$ companyName              : chr "Saba Capital Income & Opportunities Fund SBI"
#   .. .. .. ..$ symbol                   : chr "BRW"
#   .. .. .. ..$ dividend_Ex_Date         : chr "10/09/2023"
#   .. .. .. ..$ payment_Date             : chr "10/31/2023"
#   .. .. .. ..$ record_Date              : chr "10/10/2023"
#   .. .. .. ..$ dividend_Rate            : num 0.085
#   .. .. .. ..$ indicated_Annual_Dividend: num 1.02
#   .. .. .. ..$ announcement_Date        : chr "9/29/2023"
#   ..$ timeframe:List of 2
#   .. ..$ minDate: chr "1922-05-22T00:00:00"
#   .. ..$ maxDate: chr "2104-06-02T00:00:00"
#  $ message: NULL
#  $ status :List of 3
#   ..$ rCode           : int 200
#   ..$ bCodeMessage    : NULL
#   ..$ developerMessage: NULL

我显示了我的标题的结果,尽管最终你的结果也有效。

我是如何发现这个的

在我的 Firefox 浏览器中,我发送到该 URL,它立即生效。打开浏览器开发工具 (

F12
),转到 Network 选项卡,右键单击请求行(应显示 200)并选择 复制值 >> 复制请求标头,我得到了:

GET /api/calendar/dividends?date=2023-10-09 HTTP/2
Host: api.nasdaq.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Pragma: no-cache
Cache-Control: no-cache

(还有一个

Cookie:
标题,但我在不太可能发生的情况下删除了它,这对我/我的浏览器来说意味着一些个人的东西*耸耸肩*。)

我将它们转换为 R 友好的字符串参数向量

hdrs <- clipr::read_clip()
hdrs |>
  grep("^(GET|Host:) ", x = _, value = TRUE, invert = TRUE) |>
  sub("^([^:]+):", ", `\\1` =", x = _) |>
  paste(collapse = "\n") |>
  sub("^, ", "", x = _) |>
  cat("\n")
# `User-Agent` = Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/119.0
# , `Accept` = text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
# , `Accept-Language` = en-US,en;q=0.5
# , `Accept-Encoding` = gzip, deflate, br
# , `Connection` = keep-alive
# , `Upgrade-Insecure-Requests` = 1
# , `Sec-Fetch-Dest` = document
# , `Sec-Fetch-Mode` = navigate
# , `Sec-Fetch-Site` = cross-site
# , `Pragma` = no-cache
# , `Cache-Control` = no-cache 

(我真正的控制台输出没有预先添加

#
),然后我将其复制/粘贴到模板表达式中

response <- GET(url, add_headers(
  ###
))
status_code(response)

###
'ed 标题覆盖
cat
。我运行它并立即得到一个
200
,这意味着它成功了。然后我删除了所有选项并再次尝试,它挂起了(毫不奇怪)。我一次添加了几个,直到再次得到
200
,最终提出了两个产生影响的标题。

最终我找到了有效的方法(我认为你注释的代码大部分是相同的)。

数据框

我将在这里使用

dplyr
,因为它比基本列更适合于列表列。

library(dplyr)
quux <- content(response)
tibble(asOf = quux$data$calendar$asOf) %>%
  reframe(asOf, rows = lapply(quux$data$calendar$rows, as.data.frame)) %>%
  tidyr::unnest(rows)
# # A tibble: 2 × 9
#   asOf             companyName                                  symbol dividend_Ex_Date payment_Date record_Date dividend_Rate indicated_Annual_Dividend announcement_Date
#   <chr>            <chr>                                        <chr>  <chr>            <chr>        <chr>               <dbl>                     <dbl> <chr>            
# 1 Mon, Oct 9, 2023 Brady Corporation Common Stock               BRC    10/09/2023       10/31/2023   10/10/2023          0.235                      0.94 9/04/2023        
# 2 Mon, Oct 9, 2023 Saba Capital Income & Opportunities Fund SBI BRW    10/09/2023       10/31/2023   10/10/2023          0.085                      1.02 9/29/2023        

我认为

quux$data$headers
只是将
rows
中找到的名称与更易于人类阅读的名称进行映射的一种方法,因此它并没有增加太多。同样,
minDate
maxDate
可能会让您知道,但在结果框架中可能并不那么重要。

可能有更好的方法来框架化它,但这目前有效,并且可能足以获取数据。

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