Я пытаюсь получить все страницы из этой конкретной конечной точки в API, а затем преобразовать ответы .json в фрейм данных Pandas. Мой механик просматривает значение ключа в файле .json, который вложен в «мета»-ключ в разделе hasMore`. Если есть еще одна страница результатов, она вернет True, если страниц больше нет, она вернет False в качестве значений.
Я могу распечатать результат has_More, и он вернется True, поэтому я знаю, что он нашел правильное значение. Однако, когда я запускаю эту функцию, я получаю пустой список с .json или кадрами данных. Некоторое время пробовал новый код, но всегда получал пустые списки.
import requests
import json
import pandas as pd
url = "https://xxxxxxxx.xxxxxxxxx.com/projects/api/v3/tasklists"
def get_all_tasklists(url, pageSize=100, page=1):
response = requests.get(f'{url}?page = {page}&pageSize = {pageSize}',
headers = {"authorization": xxxxxxxxxxxx}
)
meta_data = json.loads(response.text)['meta']
has_More = meta_data['page']['hasMore']
timelogs = []
if has_More == True:
x = pd.json_normalize(json.loads(response.text))
timelogs.extend(x)
page += 1
else:
print(timelogs)
get_all_tasklists(url, pageSize=100, page=1)
Я предполагаю, что вы правы, потому что вы, вероятно, знаете больше о кодировании, чем я (нет даже двухмесячного опыта), но мне просто интересно, почему я не хочу, чтобы x был переписан? Я думаю, что хочу каждый раз перезаписывать его новым ответом .json, который «очищается» с помощью json_normalize?
Если вы перезапишете переменную, данные, на которые она ссылается, «потеряются». Таким образом, каждый цикл будет эффективно отбрасывать данные, полученные в предыдущем цикле. Если только вы не сохраните ссылку на него где-нибудь еще, например, в списке.






Пара проблем:
Во-первых, ваш код будет получать только одну страницу за один вызов. Учитывая, что вы назвали это get_all_xxx, это, вероятно, непреднамеренное поведение. Во-вторых, вы используете list.extend вместо list.append, что, вероятно, вам и нужно. В-третьих, эта функция не имеет возврата.
Я подправил и очистил ваш код, это должно служить минимальным рабочим примером того, что вам понадобится. По-прежнему отсутствует обработка ошибок самого запроса, но это должно быть хорошей основой. Обратите внимание, что нумерация страниц теперь находится в цикле.
import requests
import json
import pandas as pd
url = "https://xxxxxxxx.xxxxxxxxx.com/projects/api/v3/tasklists"
def get_all_tasklists(url, pageSize=100, page=1):
dataframes = []
while True:
response = requests.get(
f'{url}?page = {page}&pageSize = {pageSize}',
headers = {"authorization": xxxxxxxxxxxx}
)
meta_data = json.loads(response.text)['meta']
has_more = meta_data['page']['hasMore']
x = pd.json_normalize(json.loads(response.text))
dataframes.append(x)
if has_more:
page += 1
else:
return pd.concat(timelogs)
get_all_tasklists(url, pageSize=100, page=1)
Черт, ты хорош. Именно то, что я хотел. Это дерьмо оказалось намного сложнее, чем ожидалось (особенно для нуба). Итак, «Пока True: проверяет, что «if has_More:» истинно? Если это так, продолжайте инициировать ответ -> посмотрите мои мета_данные/has_More на предмет значения bool -> загрузите json, чтобы нормализовать и добавить в мой список DF -> If bool значение теперь False, взять все журналы времени в списке и объединить их в один?
Более или менее. Фактически этот цикл выглядит следующим образом: Fetch -> добавить в список -> если больше, ПЕРЕЙДИТЕ к 1, если больше нет, разбить и склеить список. В этом коде есть пара острых углов, которые вы, возможно, захотите решить в качестве упражнения: что произойдет, если первая страница пуста (т. е. нулевые результаты API)? Что произойдет, если вы введете несколько страниц и внезапно получите недопустимый результат JSON — будете ли вы пытаться сохранить то, что осталось, или потерпите неудачу при выполнении всей функции?
@MichaelMesa, а True: по сути, это просто бесконечный цикл. Вы выходите из него с «возвращением».
xперезаписывается в каждом цикле. Добавьте фреймы данных в список и используйтеconcat.