R代码gmapsdistance

时间:2016-12-14 02:29:52

标签: r indexoutofboundsexception api-key

我有以下代码用于查找两个地点之间的旅行时间。我使用vba来调用脚本,这就是命令args出现在顶部的原因,但出于测试目的,我只是设置变量。这一直工作到今天(没有改变任何东西),现在我一直运行结果行时出现这个错误:rowXML [[dur]]:下标超出界限时出错。

有没有人知道可能导致这个或它意味着什么?

代码:

webdriver.Firefox(executable_path='/path/to/geckodriver')

2 个答案:

答案 0 :(得分:1)

我获得了一个API密钥,重现了你的问题,然后逐行逐步完成了底层函数的源代码。

错误是由以下原因引起的:

data$Time[i] = as(rowXML[[dur]][1L]$value[1L]$text, 
                        "numeric")

因为对象dur仅包含以下内容:

> dur
[1] "duration"            "duration_in_traffic"

因此rowXML[[dur]]会抛出错误。我不知道在哪里指点,但API的变化往往比围绕它们构建的包更快。

尽管如此,您仍然可以使用源代码来获取结果,就像我一样。只需要几行代码就可以自己清理结果:

xmlChildren(results$row[[1L]])
$status
<status>OK</status> 

$duration
<duration>
  <value>20185</value>
  <text>5 hours 36 mins</text>
</duration> 

$distance
<distance>
  <value>459271</value>
  <text>459 km</text>
</distance> 

$duration_in_traffic
<duration_in_traffic>
  <value>20957</value>
  <text>5 hours 49 mins</text>
</duration_in_traffic> 

attr(,"class")
[1] "XMLInternalNodeList" "XMLNodeList"

根据你在评论中提出的要求,这里有更多关于我为此做的事情。

首先,从调用此函数中获取参数并从中创建对象(即只将每个参数作为单独的命令运行以创建对象)。接下来,加载XMLRcurl库。另外,将API密钥放在名为key的对象中。

之后,您只需获取函数的源代码并逐行运行,跳过定义函数调用的部分。在此过程中,您可以创建少量未使用的参数并将其设置为""

#    function (origin, destination, combinations = "all", mode, key = #get.api.key(), 
#              shape = "wide", avoid = "", departure = "now", dep_date = "", 
#              dep_time = "", traffic_model = "best_guess", arrival = "", 
#              arr_date = "", arr_time = "") # don't run this
  if (!(mode %in% c("driving", "walking", "bicycling", "transit"))) {
    stop("Mode of transportation not recognized. Mode should be one of ", 
         "'bicycling', 'transit', 'driving', 'walking' ")

  if (!(combinations %in% c("all", "pairwise"))) {
    stop("Combinations between origin and destination not recognized. Combinations should be one of ", 
         "'all', 'pairwise' ")
  }
  if (!(avoid %in% c("", "tolls", "highways", "ferries", "indoor"))) {
    stop("Avoid parameters not recognized. Avoid should be one of ", 
         "'tolls', 'highways', 'ferries', 'indoor' ")
  }
  if (!(traffic_model %in% c("best_guess", "pessimistic", "optimistic"))) {
    stop("Traffic model not recognized. Traffic model should be one of ", 
         "'best_guess', 'pessimistic', 'optimistic'")
  }
  seconds = "now"
  seconds_arrival = ""
  UTCtime = strptime("1970-01-01 00:00:00", "%Y-%m-%d %H:%M:%OS", 
                     tz = "GMT")
  min_secs = round(as.numeric(difftime(as.POSIXlt(Sys.time(), 
                                                  "GMT"), UTCtime, units = "secs")))
  if (dep_date != "" && dep_time != "") {
    depart = strptime(paste(dep_date, dep_time), "%Y-%m-%d %H:%M:%OS", 
                      tz = "GMT")
    seconds = round(as.numeric(difftime(depart, UTCtime, 
                                        units = "secs")))
  }
  if (departure != "now") {
    seconds = departure
  }
  if (departure != "now" && departure < min_secs) {
    stop("The departure time has to be some time in the future!")
  }
  if (dep_date != "" && dep_time == "") {
    stop("You should also specify a departure time in the format HH:MM:SS UTC")
  }
  if (dep_date == "" && dep_time != "") {
    stop("You should also specify a departure date in the format YYYY-MM-DD UTC")
  }
  if (dep_date != "" && dep_time != "" && seconds < min_secs) {
    stop("The departure time has to be some time in the future!")
  }
  if (arr_date != "" && arr_time != "") {
    arriv = strptime(paste(arr_date, arr_time), "%Y-%m-%d %H:%M:%OS", 
                     tz = "GMT")
    seconds_arrival = round(as.numeric(difftime(arriv, UTCtime, 
                                                units = "secs")))
  }
  if (arrival != "") {
    seconds_arrival = arrival
  }
  if (arrival != "" && arrival < min_secs) {
    stop("The arrival time has to be some time in the future!")
  }
  if (arr_date != "" && arr_time == "") {
    stop("You should also specify an arrival time in the format HH:MM:SS UTC")
  }
  if (arr_date == "" && arr_time != "") {
    stop("You should also specify an arrival date in the format YYYY-MM-DD UTC")
  }
  if (arr_date != "" && arr_time != "" && seconds_arrival < 
      min_secs) {
    stop("The arrival time has to be some time in the future!")
  }
  if ((dep_date != "" || dep_time != "" || departure != "now") && 
      (arr_date != "" || arr_time != "" || arrival != "")) {
    stop("Cannot input departure and arrival times. Only one can be used at a time. ")
  }
  if (combinations == "pairwise" && length(origin) != length(destination)) {
    stop("Size of origin and destination vectors must be the same when using the option: combinations == 'pairwise'")
  }
  if (combinations == "all") {
    data = expand.grid(or = origin, de = destination)
  }
  else if (combinations == "pairwise") {
    data = data.frame(or = origin, de = destination)
  }
  n = dim(data)
  n = n[1]
  data$Time = NA
  data$Distance = NA
  data$status = "OK"
  avoidmsg = ""
  if (avoid != "") {
    avoidmsg = paste0("&avoid=", avoid)
  }











  for (i in 1:1:n) {
    url = paste0("maps.googleapis.com/maps/api/distancematrix/xml?origins=", 
                 data$or[i], "&destinations=", data$de[i], "&mode=", 
                 mode, "&sensor=", "false", "&units=metric", "&departure_time=", 
                 seconds, "&traffic_model=", traffic_model, avoidmsg)
    if (!is.null(key)) {
      key = gsub(" ", "", key)
      url = paste0("https://", url, "&key=", key)
    }
    else {
      url = paste0("http://", url)
    }
    webpageXML = xmlParse(getURL(url))
    results = xmlChildren(xmlRoot(webpageXML))
    request.status = as(unlist(results$status[[1]]), "character")
    if (!is.null(results$error_message)) {
      stop(paste(c("Google API returned an error: ", xmlValue(results$error_message)), 
                 sep = ""))
    }
    if (request.status == "REQUEST_DENIED") {
      set.api.key(NULL)
      data$status[i] = "REQUEST_DENIED"
    }
    rowXML = xmlChildren(results$row[[1L]])
    Status = as(rowXML$status[1]$text, "character")
    if (Status == "ZERO_RESULTS") {
      data$status[i] = "ROUTE_NOT_FOUND"
    }
    if (Status == "NOT_FOUND") {
      data$status[i] = "PLACE_NOT_FOUND"
    }
    if (Status == "OVER_QUERY_LIMIT") {
      stop("You have exceeded your allocation of API requests for today.")
    }
    if (data$status[i] == "OK") {
      data$Distance[i] = as(rowXML$distance[1]$value[1]$text, 
                            "numeric")
      dur = grep("duration", names(rowXML), value = TRUE)
      data$Time[i] = as(rowXML[[dur]][1L]$value[1L]$text, 
                        "numeric")
    }
  }


  datadist = data[c("or", "de", "Distance")]
  datatime = data[c("or", "de", "Time")]
  datastat = data[c("or", "de", "status")]
  if (n > 1) {
    if (shape == "wide" && combinations == "all") {
      Distance = reshape(datadist, timevar = "de", idvar = c("or"), 
                         direction = "wide")
      Time = reshape(datatime, timevar = "de", idvar = c("or"), 
                     direction = "wide")
      Stat = reshape(datastat, timevar = "de", idvar = c("or"), 
                     direction = "wide")
    }
    else {
      Distance = datadist
      Time = datatime
      Stat = datastat
    }
  }
  else {
    Distance = data$Distance[i]
    Time = data$Time[i]
    Stat = data$status[i]
  }
  output = list(Time = Time, Distance = Distance, Status = Stat)

答案 1 :(得分:0)

如果您不限制使用gmapsdistance,我的googleway包会为您提供相同的结果。唯一的区别是,您目前必须指定departure_time

library(googleway)

orig <- "London"
dest <- "Paris"
api_key <- "your_api_key"

result <- google_distance(origin = c(orig, dest), destination = c(orig, dest), 
                         mode = "driving", 
                         traffic_model = "best_guess",
                         departure_time = Sys.time() + 60,
                         key = api_key)


result$rows$elements
# [[1]]
# distance.text distance.value   duration.text duration.value status
# 1           1 m              0           1 min              0     OK
# 2        459 km         459271 5 hours 36 mins          20185     OK
# 
# [[2]]
# distance.text distance.value   duration.text duration.value status
# 1        470 km         470366 5 hours 25 mins          19484     OK
# 2           1 m              0           1 min              0     OK