Ошибка клиента: (400) Неверный запрос при предоставлении URL-адреса из переменной

Я пытаюсь сократить несколько тысяч URL-адресов с помощью 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)

Я пытался кодировать URL-адреса, тестировал http и https, но ни один из вышеперечисленных способов не дал никакого эффекта. Может ли кто-нибудь предоставить мне какие-либо предложения? Заранее спасибо!

-jacek

2 ответа

Решение

У вас есть пара проблем.

Первое: фреймы данных приводят векторы символов к факторам:

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]}' в Google - то есть 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 в массивы js, а не в скаляры.)

Мне кажется, что класс mydata$Link[1] неверен, он дает коэффициент, но, вероятно, должен быть символьным.

class(mydata$Link[1])
vec<-as.character(mydata$Link[1])
Другие вопросы по тегам