如何使用 Python 从 Github API 中的所有页面获取数据?

Posted

技术标签:

【中文标题】如何使用 Python 从 Github API 中的所有页面获取数据?【英文标题】:How to get data from all pages in Github API with Python? 【发布时间】:2016-02-25 23:18:25 【问题描述】:

我正在尝试导出一个 repo 列表,它总是返回有关第一页的信息。我可以使用 URL+"?per_page=100" 扩展每页的项目数,但这还不足以获取整个列表。 我需要知道如何获取从第 1、2、...、N 页中提取数据的列表。 我正在使用请求模块,如下所示:

while i <= 2:
      r = requests.get('https://api.github.com/orgs/xxxxxxx/repos?page0&per_page=100'.format(i), auth=('My_user', 'My_passwd'))
      repo = r.json()
      j = 0
      while j < len(repo):
            print repo[j][u'full_name']
            j = j+1
      i = i + 1

我使用 while 条件,因为我知道有 2 页,我尝试以这种方式增加它,但它不起作用

【问题讨论】:

打印每次迭代生成的url,检查是否正确 你有这行:repo=p.json() 这是一个错字吗?它应该读成r.json()吗? 【参考方案1】:
import requests

url = "https://api.github.com/XXXX?simple=yes&per_page=100&page=1"
res=requests.get(url,headers="Authorization": git_token)
repos=res.json()
while 'next' in res.links.keys():
  res=requests.get(res.links['next']['url'],headers="Authorization": git_token)
  repos.extend(res.json())

如果您没有制作完整的应用程序,请使用“个人访问令牌”

https://github.com/settings/tokens

【讨论】:

谢谢!我不知道有 response.links 属性。这个答案需要被选为最佳答案。其他所有解决方案都是 hack!【参考方案2】:
        link = res.headers.get('link', None)

        if link is not None:
            link_next = [l for l in link.split(',') if 'rel="next"' in l]
            if len(link_next) > 0:
                return int(link_next[0][link_next[0].find("page=")+5:link_next[0].find(">")])

【讨论】:

【参考方案3】:

首先你使用

print(a.headers.get('link'))

这将为您提供存储库的页面数,类似于下面

<https://api.github.com/organizations/xxxx/repos?page=2&type=all>; rel="next", 

<https://api.github.com/organizations/xxxx/repos?page=8&type=all>; rel="last"

从这里你可以看到当前我们在 repo 的第一页,rel='next' 表示下一页是 2,rel='last' 告诉我们你的最后一页是 8。

知道要遍历的页数后,您只需要在获取请求时使用“=”作为页码,并将 while 循环更改到最后一个页码,而不是 len(repo),因为它会返回 100 个时间。 例如

i=1
while i <= 8:
      r = requests.get('https://api.github.com/orgs/xxxx/repos?page=0&type=all'.format(i),
                         auth=('My_user', 'My_passwd'))
      repo = r.json()
      for j in repo:
        print(repo[j][u'full_name'])
      i = i + 1

【讨论】:

【参考方案4】:

扩展上面的答案,这里有一个递归函数来处理 GitHub 分页,它将遍历所有页面,将列表与每个递归调用连接起来,最后在没有更多页面要检索时返回完整列表,除非当项目超过 500 个时,可选的故障保护返回列表。

import requests

api_get_users = 'https://api.github.com/users'


def call_api(apicall, **kwargs):

    data = kwargs.get('page', [])

    resp = requests.get(apicall)
    data += resp.json()

    # failsafe
    if len(data) > 500:
        return (data)

    if 'next' in resp.links.keys():
        return (call_api(resp.links['next']['url'], page=data))

    return (data)


data = call_api(api_get_users)

【讨论】:

如果它能够适应类似的东西会更好:data = call_api(...); while data: # do something with the data; data = call_api(...)。基本上有某种迭代器,它允许您分批检索数据,一次一页:)【参考方案5】:

据我了解,如果只返回一页数据,则链接将为无,否则即使超出最后一页,链接也会出现。在这种情况下,链接将包含先前和第一个链接。

这里有一些示例 python,它旨在简单地返回下一页的链接,如果没有下一页,则返回 None。所以可以合并到一个循环中。

link = r.headers['link']
if link is None:
    return None

# Should be a comma separated string of links
links = link.split(',')

for link in links:
    # If there is a 'next' link return the URL between the angle brackets, or None
    if 'rel="next"' in link:
        return link[link.find("<")+1:link.find(">")]
return None

【讨论】:

帮助接受的答案是否经过更好的测试。这解决了两种不同的情况。【参考方案6】:

来自github docs:

回复:

Status: 200 OK
Link: <https://api.github.com/resource?page=2>; rel="next",
      <https://api.github.com/resource?page=5>; rel="last"
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999

您将获得指向该组织的下一页和最后一页的链接。只需检查标题。

在 Python 请求中,您可以通过以下方式访问您的标头:

response.headers

它是一个包含响应头的字典。如果 link 存在,那么页面会更多,并且会包含相关信息。建议使用这些链接进行遍历,而不是自己构建。

你可以试试这样的:

import requests
url = 'https://api.github.com/orgs/xxxxxxx/repos?page0&per_page=100'
response = requests.get(url)
link = response.headers.get('link', None)
if link is not None:
    print link

如果链接不是无,它将是一个包含资源相关链接的字符串。

【讨论】:

感谢您的回答,但我已经在 github 文档上找到了,我不知道它是如何工作的。我找不到使用python实现它的方法。你能帮帮我吗? 是的,我现在正在检查。您的组织有很多页面吗? 我是使用 API 和 Python 的初学者,非常感谢您的帮助。我有一个拥有 44 个用户和 190 个 repos 的组织,因此不可能一次性下载它们,因为最多 100 个项目。 只需检查 headers dict 是否包含关键链接,在这种情况下,您可以找到下一个请求并执行此操作,直到它不显示为止。 我不知道该怎么做。我可以联系你以学习一些东西吗?我想我会很快通过聊天

以上是关于如何使用 Python 从 Github API 中的所有页面获取数据?的主要内容,如果未能解决你的问题,请参考以下文章

GitHub 的 GraphQL API 如何从 Java 中使用?

python 从Github repo导出问题到CSV(API v3)

python 从Github repo导出问题到CSV(API v3)

如何通过其 API 从网站读取数据?

如何在 C# 中使用 rest api 从 github 为用户(人)获取数据?

如何从 Github API 触发“workflow_dispatch”?