Почему разбиение на страницы GitHub дает разные результаты?

Если я выполняю поиск кода с помощью GitHub Search API и запрашиваю 100 результатов на страницу, я получаю различное количество результатов:

      import requests

# url = "https://api.github.com/search/code?q=torch +in:file + language:python+size:0..250&page=1&per_page=100"
url = "https://api.github.com/search/code?q=torch +in:file + language:python&page=1&per_page=100"

headers = {
'Authorization': 'Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}

response = requests.request("GET", url, headers=headers).json()

print(len(response['items']))

Благодаря этому ответу у меня есть следующий обходной путь: я запускаю запрос несколько раз, пока не получу требуемые результаты на странице.

Мой текущий проект требует, чтобы я перебирал поисковый API в поисках файлов разного размера. Я в основном повторяю описанную здесь процедуру . Поэтому мой код выглядит примерно так:

      url = "https://api.github.com/search/code?q=torch +in:file + language:python+size:0..250&page=1&per_page=100"

В этом случае я не знаю заранее, сколько результатов должна иметь страница. Может ли кто-нибудь сказать мне обходной путь для этого? Может быть, я неправильно использую API поиска?

1 ответ

GitHub предоставляет документацию об использовании разбиения на страницы в REST API. Каждый ответ включает заголовок, содержащий ссылку на следующий набор результатов (наряду с другими ссылками); вы можете использовать это для перебора всего набора результатов.

Для конкретного поиска, который вы выполняете («каждый файл Python, содержащий слово «факел»»), вы довольно быстро столкнетесь с ограничениями скорости, но, например, следующий код будет перебирать результаты, 10 за раз (или около того), пока не будет прочитано 50 или более результатов:

      import os
import requests
import httplink

url = "https://api.github.com/search/code?q=torch +in:file + language:python&page=1&per_page=10"

headers = {"Authorization": f'Token {os.environ["GITHUB_TOKEN"]}'}

# This is the total number of items we want to fetch
max_items = 50

# This is how many items we've retrieved so far
total = 0

try:
    while True:
        res = requests.request("GET", url, headers=headers)
        res.raise_for_status()
        link = httplink.parse_link_header(res.headers["link"])

        data = res.json()
        for i, item in enumerate(data["items"], start=total):
            print(f'[{i}] {item["html_url"]}')

        if "next" not in link:
            break

        total += len(data["items"])
        if total >= max_items:
            break

        url = link["next"].target
except requests.exceptions.HTTPError as err:
    print(err)
    print(err.response.text)

Здесь я используюhttplinkмодуль для разбораLinkзаголовок, но вы можете сделать то же самое с соответствующим регулярным выражением иreмодуль.

Другие вопросы по тегам