客户端错误:(400)从变量提供URL时出现错误请求

时间:2014-10-08 04:59:43

标签: r google-api httr google-url-shortener

我正在尝试使用Google API缩短数千个网址。我正在使用httr来做POST。每当我提供一个URL作为变量发布时,我得到“客户端错误:(400)错误请求”,但是当相同的URL直接作为字符串提供时(例如“http://www.google.com”),一切正常。下面提供了一个最小的例子:

library(httr)
library(httpuv)

# enter data
mydata <- data.frame(Link = "http://www.google.com")

# 1. Find OAuth settings for google:
#    https://developers.google.com/accounts/docs/OAuth2InstalledApp
oauth_endpoints("google")

# 2. Register an application at https://cloud.google.com/console#/project
myapp <- oauth_app("google", key = "key goes here", secret = "secret goes here")

# 3. Get OAuth credentials
google_token <- oauth2.0_token(oauth_endpoints("google"), myapp, scope = "https://www.googleapis.com/auth/urlshortener")

返回错误:客户端错误:(400)错误请求

req <- POST('https://www.googleapis.com/urlshortener/v1/url?fields=id',
       add_headers("Content-Type"="application/json"),
       body='{"longUrl": mydata$Link[1]}', config(token = google_token))
stop_for_status(req)

这很好用

req <- POST('https://www.googleapis.com/urlshortener/v1/url?fields=id',
       add_headers("Content-Type"="application/json"),
       body='{"longUrl": "http://www.google.com"}', config(token = google_token))
stop_for_status(req)

我尝试编码网址,测试http和https,但以上都没有任何效果。任何人都可以向我提出任何建议吗?提前谢谢!

-jacek

2 个答案:

答案 0 :(得分:1)

在我看来,mydata $ Link [1]的类是不正确的,它给出因子,但可能应该是字符。

class(mydata$Link[1])
vec<-as.character(mydata$Link[1])

答案 1 :(得分:1)

你有几个问题。

首先:数据框将字符向量强制转换为因子:

mydata <- data.frame(link = "http://www.google.com")
class(mydata$link)
#> [1] "factor"

mydata <- data.frame(link = "http://www.google.com", stringsAsFactors = FALSE)
class(mydata$link)
#> [1] "character"

其次,您将'{"longUrl": mydata$Link[1]}'发送给谷歌 - 即 您提交的longUrl是mydata$Link[1],而不是 http://www.google.com。最简单的方法是使用jsonlite来解决这个问题 做编码:

req <- POST('https://www.googleapis.com/urlshortener/v1/url?fields=id',
  body = list(longUrl = jsonlite::unbox(mydata$link[1]),
  encode = "json",
  config(token = google_token)
)
stop_for_status(req)

(不幸的是unbox()是必要的,因为jsonlite默认为 将长度为1的vetors转换为js数组,而不是标量。)