【问题标题】:How to specify user agent when using github API?使用 github API 时如何指定用户代理?
【发布时间】:2021-08-24 15:19:56
【问题描述】:

我想获取 Github 存储库上的文件列表。我关注了this answer,但我注意到有时我会遇到 HTTP 403 错误。例如,如果我运行以下代码:

library(httr)

for (i in 1:10) {
  req <- GET("https://api.github.com/repos/etiennebacher/tidytuesday/git/trees/master?recursive=1")
  stop_for_status(req)
}

> Error: Forbidden (HTTP 403).

(请注意,我实际上并不想运行此 GET 请求 10 次,这只是我发现的模拟问题的最简单方法。)

在网上搜索了一下,我找到了this answer,它解释了 Github API 需要 GitHub 用户名或应用程序的名称来获取请求的 User-Agent 标头值。

但是在GET() 中添加user_agent("etiennebacher") 并不会改变任何东西。在这种情况下我应该如何指定用户代理?

也在RStudio Community上提问

【问题讨论】:

  • 也许用户代理是别的东西:rdrr.io/cran/httr/man/user_agent.html。我似乎记得代理是软件的名称。例如。 Mozilla 或 chrome。
  • 不一定,例如GET(url = "http://httpbin.org/user-agent") 给出"user-agent": "libcurl/7.64.1 r-curl/4.3.2 httr/1.4.2"。但我们也可以自定义它们,例如GET(url = "http://httpbin.org/user-agent", user_agent("hello")) 给出"user-agent": "hello"。但由于某种原因,我无法让 github api 使用它
  • 我不知道答案,但我会尝试 libcurl 规范或其他两个规范之一。
  • 您得到的错误是否只有“禁止”?或者它实际上是否返回有关“用户代理”的特定消息。 GET 请求确实发送了一个默认用户代理,而httr::user_agent() 函数在包含在GET("http:///", user_agent("whatever")) 中时确实会改变它。您是否进行过任何形式的身份验证?未经身份验证的请求仅限于每小时几个请求。
  • @MrFlick 确实消息是API rate limit exceeded...,可以通过身份验证解决。我还找到了包gh,它使验证更容易(通过gh::gh_whoami())。这在本地解决了它,但我不知道如何在 Github 操作中进行身份验证(这是上面的代码应该运行的地方)。我读过this page,但我还不知道如何将GITHUB_TOKEN 作为R 函数的输入传递。如果我找不到方法,我会为此提出另一个问题。

标签: r httr


【解决方案1】:

正如@MrFlick 所评论的,这里的 HTTP 403 表示超出了 API 速率限制。解决此问题的一种方法是在发出请求时进行身份验证,因为速率限制为from 60 to 5,000 requests per hour。使用包gh(及其同名函数)更容易做到这一点。这可以通过在gh() 中指定.token = &lt;PAT&gt;(其中&lt;PAT&gt; 是您的GitHub 个人访问令牌)在本地完成。

要获取特定 repo 中的文件列表,您可以将 gh() 的输出保存在 JSON 文件中,然后使用 jsonlite::fromJSON() 读取它。然后获取文件列表就很简单了。

底线,这是可行的:

library(gh)
library(jsonlite)

tmp_file <- tempfile(fileext = ".json")

gh::gh("https://api.github.com/repos/etiennebacher/tidytuesday/git/trees/master?recursive=1", .destfile = tmp_file, .token = <PAT>)

jsonlite::fromJSON(tmp_file)$tree$path

奖励:如何在 Github Actions 中进行身份验证

我在原帖中没有说,但是这个 GET 请求应该是在 Github 操作中发出的。由于无法手动提供 PAT 作为令牌,因此需要在 .yaml 文件中定义令牌,然后在 .R 文件中传递其值。

test.R

library(gh)
library(jsonlite)

tmp_file <- tempfile(fileext = ".json")

gh::gh("https://api.github.com/repos/etiennebacher/tidytuesday/git/trees/master?recursive=1", .destfile = tmp_file, .token = github_token)

jsonlite::fromJSON(tmp_file)$tree$path

GitHub 操作:

on:
  push:
    branches: master

jobs:
  build:
    runs-on: macOS-latest
    steps:
      - uses: actions/checkout@v2
      - uses: r-lib/actions/setup-r@master
      - run: |
          github_token <- "${{ secrets.GITHUB_TOKEN }}"
          install.packages(c("gh", "jsonlite"))
          source("test.R"),
        shell: Rscript {0}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多