OpenStreetMap Nominatim API批量地址转坐标脚本故障排查
批量获取维也纳地址坐标失败的修复方案
问题背景
我需要为一批维也纳地址获取坐标,数据集已通过read_csv读入为data对象,依赖tidyverse和jsonlite库,仅使用街道列Straße与门牌号列ON,所有地址归属奥地利维也纳。
地址格式化代码如下,生成的格式(如1+milanweg,+vienna)符合OpenStreetMap要求,手动调用API能正常返回坐标:
data$formatted_address <- paste(ifelse(is.na(data$ON), "", data$ON), "+", tolower(data$Straße), ",+vienna", sep = "")
但使用以下批量请求脚本时,lat和lon始终为空,需修复:
data$coordinates <- data.frame(lat = NA, lon = NA) for (i in 1:nrow(data)) { result <- try(readLines(paste0("https://nominatim.openstreetmap.org/search?q=", URLencode(data$formatted_address[i]), "&format=json&polygon=1&addressdetails=1")), silent = TRUE) if (!inherits(result, "try-error")) { if (length(result) > 0) { result <- fromJSON(result) if (length(result) > 0 && is.list(result[[1]])) { data$coordinates[i, ] <- c(result[[1]]$lat, result[[1]]$lon) } } } }
问题原因
- 嵌套数据框赋值错误:
data$coordinates是嵌套在data中的数据框,R无法正确识别data$coordinates[i, ]的行赋值逻辑,导致坐标无法写入。 - 无请求延迟触发限流:Nominatim API限制每秒最多1次请求,批量请求无延迟会被服务器拒绝,返回空结果。
- 坐标类型未转换:API返回的
lat和lon是字符串类型,直接赋值会导致存储异常。
修复后的脚本
# 直接初始化lat和lon为data的列,避免嵌套数据框 data$lat <- NA_real_ data$lon <- NA_real_ for (i in 1:nrow(data)) { # 跳过空地址或仅含城市的无效地址 if (is.na(data$formatted_address[i]) || data$formatted_address[i] == ",+vienna") { next } # 构造请求URL request_url <- paste0( "https://nominatim.openstreetmap.org/search?q=", URLencode(data$formatted_address[i]), "&format=json&polygon=1&addressdetails=1" ) # 直接用fromJSON请求并解析,简化逻辑 api_result <- try(fromJSON(request_url), silent = TRUE) if (!inherits(api_result, "try-error") && length(api_result) > 0) { # 将字符串坐标转为数值型后赋值 data$lat[i] <- as.numeric(api_result[[1]]$lat) data$lon[i] <- as.numeric(api_result[[1]]$lon) } # 添加1秒延迟,遵守API请求频率限制 Sys.sleep(1) }
关键优化说明
- 取消嵌套结构:把
lat和lon设为data的直接列,解决赋值索引问题。 - 添加请求延迟:
Sys.sleep(1)确保符合Nominatim的请求频率规则,避免被限流。 - 简化请求逻辑:直接使用
fromJSON发起请求并解析,减少中间步骤的错误点。 - 过滤无效地址:跳过无街道信息的无效地址,减少无效请求。
- 类型转换:将API返回的字符串坐标转为数值型,保证数据格式正确。
内容的提问来源于stack exchange,提问作者DunkinDont
相关产品推荐
相关产品推荐

