【问题标题】:Using the openpaths.cc API with R将 openpaths.cc API 与 R 一起使用
【发布时间】:2014-03-15 09:13:39
【问题描述】:

我试图从openpaths.cc 中提取我的位置数据以将其与 R 一起使用。 该 API 使用 OAuth 并记录在 here,但是,它仅提供 Python 中的示例。

在查看了如何在 R 中处理 OAuth(我几乎不熟悉)之后,我发现了 ROAuth,因此我使用了提供的用法示例作为基础。

根据 API 文档,所有请求的端点都是 https://openpaths.cc/api/1,我有我的访问密钥和访问密码,所以我天真地将它们插入 cKey、cSecret、reqURL、@ 987654329@、authURL 和 testURL,但由于 credentials$handshake() 行的结果只收到“错误请求”。

reqURL <- "https://openpaths.cc/api/1"
accessURL <- "https://openpaths.cc/api/1"
authURL <- "https://openpaths.cc/api/1"
cKey <- "key"
cSecret <- "secret"
testURL <- "https://openpaths.cc/api/1"
credentials <- OAuthFactory$new(consumerKey=cKey,
                                consumerSecret=cSecret,
                                requestURL=reqURL,
                                accessURL=accessURL,
                                authURL=authURL,
                                needsVerifier=TRUE)
credentials$handshake()
## the GET isn’t strictly necessary as that’s the default
credentials$OAuthRequest(testURL, "GET")

虽然我觉得我不知道自己在做什么,但我至少验证了 ROAuth 能够使用 HMAC-SHA1 方法,这是 openpaths 所要求的。

编辑:我安装了 ROAuth 0.9.3 版

EDIT2:在了解httr 之后,我认为这可能是该任务的合适库,但是我仍然无法产生任何可用的结果,因为通过oauth1.0_token 创建令牌只会再次导致Bad request . 我认为我的主要问题是 openpaths.cc 缺少 API 文档。有了所有这些工具,我仍然不知道如何正确使用它们。

【问题讨论】:

  • 问题是什么 - 您是否专门解决了握手的错误请求?还是您在问您是否正确使用了 ROAuth?
  • 两者,或多或少。我的主要问题是我首先不知道如何处理 openpaths API,并且除了 python 示例之外没有找到任何文档,所以我什至不知道我在用 ROAuth 做什么说得通。不幸的是,openpaths 在这里似乎没有标签,而且我的声誉太低,无法创建。
  • 有趣的问题,我也搞不定。请注意,httr 包包含一些 oauth 示例,这些示例可能比 ROAuth 更容易适应此问题。
  • 我会在 openpaths 再次启动后立即为您提供一个 httr 示例。您的设置肯定有问题,因为 reqURL 等都应该不同。
  • 啊,这个用的是两条腿的OAuth,有点不寻常。我需要比预期更长的时间才能得到有效的东西。

标签: r api oauth httr


【解决方案1】:

我在这个问题上取得了一些进展,虽然它具有挑战性,因为 到网站的脆弱性,以及他们的自定义 OAuth 流程 使用。首先,您需要安装 httr 的开发版本 - 这个 导出一些以前的内部函数。

devtools::install_github("hadley/httr")

OpenPaths 的不寻常之处在于应用程序的秘密和密钥与 令牌和令牌秘密。这意味着我们需要编写自定义身份验证 标题:

library(httr)

app <- oauth_app("OpenPaths", "JSLEKAPZIMFVFROHBDT4KNBVSI")
#> Using secret stored in environment variable OPENPATHS_CONSUMER_SECRET

# Implement custom header for 2-leg authentication, and oauth_body_hash 
auth_header <- function(url, method = "GET") {
  oauth_signature(url, method, app, app$key, app$secret,
    # Use sha1 of empty string since http request body is empty
    body_hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709")  
}

然后您可以使用它来签署您的请求。这目前正在失败 对我来说,因为该网站似乎(再次)关闭。

url <- "https://openpaths.cc/api/1"
r <- GET(url, oauth_header(auth_header(url)))
stop_for_status(r)
content(r)

【讨论】:

  • 在过去的几个小时里我已经尝试了几次,但除了偶尔的超时外,我只收到了XML content does not seem to be XML: '400: NOT AUTHORIZED' 作为答案。我对 API 的明显古怪感到有点恼火,因为该网站表示它旨在非常直接地使用。至于片状——我不记得该网站以前是片状的,这似乎是(不幸的是时间上)最近的问题。
【解决方案2】:

这是我所知道的。我收到“400 Not Authorized”,可能是因为我的 openpaths 帐户没有连接到foursquare,也可能是代码有问题。请尝试一下!

所需的包:

library(RCurl)
library(digest)
library(base64)

部分功能借鉴/改编自ROAuth:

## Get a random sequence of characters.
## Nonce - number used only once.
genNonce <- function(len = 15L + sample(1:16, 1L)) {
  els <- c(letters, LETTERS, 0:9, "_")
  paste(sample(els, len, replace = TRUE), collapse = "")
}

## this function is derived from utils::URLencode
## Characters not in the unreserved character set ([RFC3986] section 2.3) MUST be encoded
##   unreserved = ALPHA, DIGIT, '-', '.', '_', '~'
## cf. http://oauth.net/core/1.0/#encoding_parameters
encodeURI <- function(URI, ...) {
  if (!is.character(URI)) {
    URI
  } else {
    OK <- "[^-A-Za-z0-9_.~]"
    x <- strsplit(URI, "")[[1L]]
    z <- grep(OK, x)
    if (length(z)) {
      y <- sapply(x[z], function(x) paste("%", toupper(as.character(charToRaw(x))),
                                          sep = "", collapse = ""))
      x[z] <- y
    }
      paste(x, collapse = "")
  }
}

## we escape the values of the parameters in a special way that escapes
## the resulting % prefix in the escaped characters, e.g. %20 becomes
## %2520 as %25 is the escape for %
## cf. http://tools.ietf.org/html/rfc5849#section-3.4.1.3.2
normalizeParams <- function(params, escapeFun) {
  names(params) <- sapply(names(params), escapeFun, post.amp = TRUE)
  params <- sapply(params, escapeFun, post.amp = TRUE)
  ## If two or more parameters share the same name, they are sorted by their value.
  params <- params[order(names(params), params)]
  return(paste(names(params), params, sep = "=", collapse = "&"))
}

## From Ozaki Toru's code at https://gist.github.com/586468
signWithHMAC <- function(key, data) {
  blockSize <- 64
  hashlength <- 20
  innerpad   <- rawToBits(as.raw(rep(0x36, blockSize)))
  outerpad   <- rawToBits(as.raw(rep(0x5C, blockSize)))
  zero       <- rep(0 ,64)

  HexdigestToDigest <- function(digest) {
    as.raw(strtoi(substring(digest, (1:hashlength)*2-1,
                            (1:hashlength)*2), base=16))
  }

  mac <- function(pad, text) {
    HexdigestToDigest(digest(append(packBits(xor(key, pad)), text),
                             algo='sha1', serialize=FALSE))
  }

  if(nchar(key) >= 64) {
    keyDigested <- digest(key, algo="sha1", serialize=FALSE)
    key <- intToUtf8(strtoi(HexdigestToDigest(keyDigested), base=16))
  }
  key <- rawToBits(as.raw(append(utf8ToInt(key), zero)[1:blockSize]))

  base64(mac(outerpad, mac(innerpad, charToRaw(data))))[1]
}

## Sign an request made up of the URL, the parameters as a named character
## vector the consumer key and secret and the token and token secret.
signRequest  <- function(uri, consumerKey, consumerSecret, params=character(), 
                         oauthKey = "", oauthSecret = "", httpMethod = "GET",
                         nonce = genNonce(),
                         timestamp = Sys.time()) {
  httpMethod <- toupper(httpMethod)

  params["oauth_nonce"] <- nonce
  params["oauth_timestamp"] <- as.integer(timestamp)
  params["oauth_consumer_key"] <- consumerKey
  params["oauth_signature_method"] <- 'HMAC-SHA1'
  params["oauth_version"] <- '1.0'
  if(oauthKey != "") params["oauth_token"] <- oauthKey
  odat <- paste(
      encodeURI(httpMethod), encodeURI(uri), 
      encodeURI(normalizeParams(params, encodeURI), post.amp = TRUE),
      sep = "&"
  )
  okey <- encodeURI(consumerSecret)
  if(oauthSecret != "") okey <- paste(okey, encodeURI(oauthSecret), sep = "&")

  params["oauth_signature"] <- signWithHMAC(okey, odat)
  return(params)
}

现在这个函数尝试复制 openpaths 网站上的示例:

openpaths <- function(
    access_key=getOption("openpaths.access_key"), 
    secret_key=getOption("openpaths.secret_key"), 
    curl=getCurlHandle()) {

    uri <- 'https://openpaths.cc/api/1'
    params <- signRequest(uri, consumerKey=access_key, consumerSecret=secret_key)
    oa_header <- paste(names(params), params, sep="=", collapse=",")
    ret <- getURL(
        uri,
        curl=curl,
        .opts=list(
            header=TRUE,
            verbose=TRUE,
            httpheader=c(Authorization=paste("OAuth ", oa_header, sep="")),
            ssl.verifypeer = TRUE, 
            ssl.verifyhost = TRUE, 
            cainfo = system.file("CurlSSL", "cacert.pem", package = "RCurl")
        )
    )
    return(ret)
}

【讨论】:

  • 嗯,当我获取你的函数时,插入我的密钥并尝试test &lt;- openptahs(),它告诉我CURLOPT_SSL_VERIFYHOST no longer supports 1 as value! 和后来的HTTP/1.1 400 Bad Request……因为这超出了我的想象,我不知道真的知道如何解释这一点。
  • 你的RCurl是什么版本的?
  • 1.95-4.1 – 我刚才还检查了包更新(我正在使用 Rstudio),没有 RCurl。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
  • 1970-01-01
相关资源
最近更新 更多