使用GET函数从循环运行结果

时间:2017-10-17 23:45:10

标签: r api url

我试图将结果运行到GET中的URL列表

网址标准<​​/ h1>
lon <- as.list(seq(-124.4531, -68.02734, by=5.9180))
lat <- as.list(seq(25.7998, 49.0090, by=5.6667))
z <- expand.grid(lon,lat)
z <- as.data.frame(cbind("lon" = unlist(z$Var1), "lat" = unlist(z$Var2)))
n = dim(z)[1]

创建URL列表

for(i in 1:n) {
  for(j in 1:n) {
    URL<- paste0("https://maps.googleapis.com/maps/api/place/radarsearch/json?location=", as.character(z$lat[j]), ",", as.character(z$lon[i]),                 "&radius=50000&name=MetroPCS&key=key")

    print(URL)
  }
}

运行具有GET功能的URL列表

loop<-function(URL){
  res<-GET("URL")
  jasonAnse<-contnet(res,"text")
  myDataframe<- jsonlite::fromJSON(content(res,"text"))
}

myDataframe

能够运行所有记录,但只能存储最后一条记录

但似乎GET功能只能运行最后一条记录。不确定循环或GET()函数是否错误。

1 个答案:

答案 0 :(得分:0)

每当我看到一个问题说“1或更多”的东西时,我倾向于考虑做一次事情并迭代矢量或列表中的所有项目。你开始以这种方式思考,但是在你的循环中,你每次都分配 over URL并且只保存最后一个。即使你保存了所有的URL,GET一次只能检索一个,所以你也需要迭代该函数。

这个演示主要是概念,没有真正证据证明它有效。因为您在问题中包含了一个实际的API密钥,所以它已经用尽了。 (你可能想从问题中删除它。)无论如何,我有点相信这个概念可以将函数应用到一个列表中,所以尽管我还没有验证你从中得到了一个巨大的data.frame,也许我会幸运的。

z <- expand.grid(lon = seq(-124.4531, -68.02734, by=5.9180),
                 lat = seq(25.7998, 49.0090, by=5.6667))
head(z)
#         lon     lat
# 1 -124.4531 25.7998
# 2 -118.5351 25.7998
# 3 -112.6171 25.7998
# 4 -106.6991 25.7998
# 5 -100.7811 25.7998
# 6  -94.8631 25.7998

mapply(和Map)通过将来自矢量/列表的 1个或多个参数应用于单个函数(第一个参数)来工作。在某些语言中,它被认为是“拉上论据”。考虑一下:

mapply(function(x,y,z) x+y-z,
       c(1,2,3,4), c(5,6,7,8), c(9,10,11,12))

对匿名函数的第一次调用将执行1+5-9;第二,2+6-10;使用它还有其他一些技巧,但回顾你的问题:

URLs <- mapply(sprintf,
               list("https://maps.googleapis.com/maps/api/place/radarsearch/json?location=%s,%s&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"),
               z$lat, z$lon)

修改:我之前在z$lat内已z$lonmapply被撤销,已修复。)

函数sprintf接受任意数量的参数:第一个始终是格式化字符串,第二个和更远(如果有)始终是填充格式化字符串的参数/对象。 list("htt...")参数只为sprintf的每个调用提供了该参数,因此函数调用被分解为:

sprintf("https...", z$lon[1], z$lon[2])
sprintf("https...", z$lon[2], z$lon[2])
# ...
sprintf("https...", z$lon[50], z$lon[50])

这些调用被包裹回character向量,长度为50。

(URLs <- head(URLs)) # doing this for a simpler demo, since I don't need all 50
# [1] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-124.4531,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [2] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-118.5351,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [3] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-112.6171,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [4] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-106.6991,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [5] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-100.7811,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU"
# [6] "https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-94.8631,25.7998&radius=50000&name=MetroPCS&key=AIzaSyA3u4HwTGiUsHP7FNUKkjbYcHHe1xFBDTU" 

我们仍然有一个“1或更多”的列表,因此我们可以继续使用lapply逻辑:

HTMLs <- lapply(URLs, GET)
HTMLs[1]
# [[1]]
# Response [https://maps.googleapis.com/maps/api/place/radarsearch/json?location=-124.4531,25.7998&radius=50000&name=MetroPCS]
#   Date: 2017-10-18 03:23
#   Status: 200
#   Content-Type: application/json; charset=UTF-8
#   Size: 141 B
# {
#    "error_message" : "This service requires an API key.",
#    "html_attributions" : [],
#    "results" : [],
#    "status" : "REQUEST_DENIED"
# }

在这种情况下,我得到了一个失败(这将减少我以后可以做的事情),但是这个输出显示你的HTMLs变量应该是50的长度,每个变量都是这样的。

继续,虽然从现在开始它没有经过测试。我相信你已经测试过这个,一次只能使用一个URL。

contents <- lapply(HTMLs, content, "text")
myDataFrames <- lapply(contents, jsonlite::fromJSON)

最后一个应该是data.frame的列表,这很棒!我通常会做两件事之一:如果我可以轻松地将它们(rbind?)组合成一个data.frame,那么我会这样做:

myDataFrame <- do.call(rbind.data.frame, c(myDataFrames, list(stringsAsFactors = FALSE)))

stringsAsFactors的使用主要是文体,但显示如何在需要时添加参数。)

但是,如果将它们分开是有益的(可能它们不是同质结构),那么在列表上运行(重复lapply或相关)仍然很容易。

可以通过一次调用来证明这一点的合理性:

myDataFrames <- lapply(URLs, function(u) {
  html <- GET(u)
  cont <- cont(html, "text")
  jsonlite::fromJSON(cont)
})

这没有错。但是,特别是在开发过程中,保留不同对象的中间列表可能是有益的。