避免在R中进行URL编码

3
我正在尝试从Google Geocoding API获取纬度/经度,但是当地址包含丹麦本地字符时,请求会失败。我怀疑是因为httr::GET函数对URL进行了编码,但我不确定自己是否正确。如果您直接将此链接复制/粘贴到浏览器中,您将获得有效结果:http://maps.googleapis.com/maps/api/geocode/json?address=Søholmen+9,+4500+Denmark 但是下面的代码无效,即使URL在解析为GET函数之前相同。如果我使用不带本地字符的地址,它就可以工作。
library(httr)
library(jsonlite)
library(stringr)

address <- "Søholmen 9, 4500 Denmark"
# address <- "Kronprinsesse Sofies Vej 6, 2000 Denmark"

base_url <- "http://maps.googleapis.com/maps/api/geocode/json?"

# An address OR components
geo_url <- paste0(base_url, "address=", str_replace_all(address, pattern = " ", replacement = "+"))

# Get the result
# get the content
# Parse the JSON
temp_geo_results <- httr::GET(url = URLencode(URL = geo_url), verbose())
temp_geo_results <- httr::content(temp_geo_results, as = "text")
temp_geo_results <- jsonlite::fromJSON(temp_geo_results)

这是我的sessionInfo()

R version 3.1.2 (2014-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=Danish_Denmark.1252  LC_CTYPE=Danish_Denmark.1252        LC_MONETARY=Danish_Denmark.1252
[4] LC_NUMERIC=C                    LC_TIME=Danish_Denmark.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] stringr_0.6.2   jsonlite_0.9.10 httr_0.5       

loaded via a namespace (and not attached):
[1] RCurl_1.95-4.3 tools_3.1.2 

编辑:我删除了一行不必要的代码,并添加了我的会话信息。


@LauriK 如果我将您的URL复制/粘贴到我的浏览器中并使用GET函数,则会收到“错误请求”/“零结果”的返回。 - KERO
奇怪,这在我的Chrome浏览器上可以运行。 - LauriK
这些编码问题有时会让我困扰,我不得不去研究一下。我也使用Chrome,并将我的R文档保存为UTF-8格式。 - KERO
你介意在 Github 上将此问题报告为 httr 的 bug 吗? - hadley
当然,我会立即处理。 - KERO
显示剩余2条评论
4个回答

4
这似乎是一个编码问题。
下面的方法对我来说可以正常工作:
address <- "Søholmen 9, 4500 Denmark"
u <- sprintf("http://maps.googleapis.com/maps/api/geocode/json?address=%s", 
             gsub('\\s+', '+', enc2utf8(address)))

fromJSON(content(GET(u), as='text'))

2
我尝试使用enc2utf8来包装地址,这也起作用了。我以为将R文件保存为UTF-8格式可以避免这些问题。显然不行。感谢您的帮助。非常感激! - KERO
好的,enc2utf8 在这里可能更合适。我会进行编辑。 - jbaums

0

我如何解决类似问题:在rawToCharfromJSON之间设置编码,如下所示(不可执行)。

library(httr)
library(jsonlite)

call_api <- GET("YOUR_URL",
                  add_headers(.headers=c(`Authorization` = "YOUR_KEY")))

strange_characters <- rawToChar(call_api$content) #wherever the raw_data is

# if you pass Encoding(strange_characters) you will get "unknown". So run the line below.
Encoding(strange_characters) <- "UTF-8" 
  
right_characters <- fromJSON(strange_characters)

0
你可以使用rvest包。
library(rvest); library(jsonlite)
address <- "Søholmen 9, 4500 Denmark"
# address <- "Kronprinsesse Sofies Vej 6, 2000 Denmark"
base_url <- "http://maps.googleapis.com/maps/api/geocode/json?"

# An address OR components
geo_url <- paste0(base_url, "address=", str_replace_all(address, pattern = " ", replacement = "+"))
geo_url <- iconv(geo_url, to="UTF-8")

temp_geo_results <- html_text(html_nodes(html(geo_url) , "p"))
temp_geo_results <- fromJSON(temp_geo_results)

-1

我可以分享一下我用我的语言解决同样问题的粗略方法:

deencode <- function(text){
  output <- NULL
  for(i in 1:length(text)){
    temp <- text[i]
    temp <- gsub("ā", "a", temp)  
    temp <- gsub("Ā", "A", temp)
    temp <- gsub("č", "c", temp)
    temp <- gsub("Č", "C", temp)
    temp <- gsub("ē", "e", temp)
    temp <- gsub("Ē", "E", temp)
    temp <- gsub("ģ", "g", temp)
    temp <- gsub("Ģ", "G", temp)
    temp <- gsub("ī", "i", temp)
    temp <- gsub("Ī", "I", temp)
    temp <- gsub("ķ", "k", temp)
    temp <- gsub("Ķ", "K", temp)
    temp <- gsub("ļ", "l", temp)
    temp <- gsub("Ļ", "L", temp)
    temp <- gsub("ņ", "n", temp)
    temp <- gsub("Ņ", "N", temp)
    temp <- gsub("š", "s", temp)
    temp <- gsub("Š", "S", temp)
    temp <- gsub("ū", "u", temp)
    temp <- gsub("Ū", "u", temp)
    temp <- gsub("ž", "z", temp)
    temp <- gsub("Ž", "Z", temp)
    output <- c(output, temp)
  }
  return(output)
}

在这种简单的替换之后,至少在Google地理编码API中,一切都正常工作了。


gsub 是向量化的,所以您不需要遍历 text 的每个元素 :) - jbaums

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接