如何使用 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)