Почему API отдаёт данные частями, как понять, что загружены все страницы, и что делать, если источник меняется во время чтения.
Почему источник отдаёт только часть
Представьте каталог товаров, в котором десятки тысяч позиций. Если сервис попытался бы отправить весь каталог за один ответ, ожидание и нагрузка могли бы стать слишком большими. Поэтому многие программные интерфейсы, или API, возвращают записи небольшими порциями. Каждая порция называется страницей. Это относится к данным, а не к страницам сайта, которые листает посетитель.
Читатель первого ответа может увидеть вполне правдоподобный набор товаров и ошибочно принять его за полный. Документация GitHub описывает именно такое поведение: большой набор результатов делится на страницы, а ответ содержит способ перейти к следующей. Microsoft Graph тоже сообщает адрес следующей порции, пока данные не закончились. Способ перехода зависит от конкретного источника, поэтому его нужно узнать из документации сервиса.
Условный пример каталога
Допустим, у условного магазина 250 карточек, а один ответ содержит 100. Для полного набора понадобятся три порции: две по 100 карточек и одна с оставшимися 50. Если остановиться после первой, отчёт покажет меньше половины каталога. Ошибка может остаться незаметной, если никто заранее не знает точного числа товаров.
Для полноты недостаточно просто повторить обращение к тому же адресу. Нужно следовать указанию на следующую страницу либо другому правилу, которое установил владелец API. Некоторые сервисы передают номер, другие — специальную ссылку или метку продолжения. Подставлять своё предположение о номерах там, где выдана готовая ссылка, рискованно: она может содержать необходимые условия выборки.
Как убедиться, что выгрузка завершена
Завершение означает не «получена большая порция», а «источник больше не предлагает продолжения» по своим правилам. Полезно также сверить число полученных записей с контрольным показателем, если сервис публикует его отдельно. Однако такой показатель может меняться вместе с источником, поэтому расхождение сначала исследуют, а не автоматически объявляют ошибкой.
После каждой порции стоит понимать, что уже было сохранено, а что ещё ожидается. Если загрузка прервётся на середине, команда должна знать, откуда продолжить, и не добавлять одинаковые записи повторно. О том, как сопоставлять результат с источником, читайте материал о сверке данных после переноса.
Что меняется во время чтения
Представим, что между первой и второй порцией в каталог добавили новый товар. В зависимости от порядка и способа деления на страницы граница между порциями может сдвинуться. Тогда одна карточка встретится дважды либо какая-то не попадёт в выгрузку. Это возможный риск динамического источника, а не обязательный недостаток каждого API.
Если нужна точная копия на определённый момент, проверьте, поддерживает ли источник стабильный снимок, фильтр по времени изменения или иной способ согласованного чтения. Без такой возможности честнее указать, что выгрузка отражает период сбора, а не мгновенное состояние. При регулярных загрузках полезно сверять идентификаторы и изменения, а не только итоговое число строк.
Когда искать другой способ
Постраничный API удобен для умеренных объёмов и регулярного получения изменений. Но если приходится каждый день перечитывать огромный каталог целиком, стоит спросить у владельца системы о выгрузке файла, потоке изменений или отдельном аналитическом интерфейсе. Выбор зависит от доступных возможностей, частоты обновления и требований к полноте.
Главный практический вопрос прост: можно ли доказать, что были прочитаны все необходимые части и понятен момент, к которому относится результат? Пагинация решает задачу доставки больших наборов порциями. Контроль полноты, повторов и времени изменений остаётся задачей команды, которая использует данные. Больше о роли такой команды рассказано в статье об инструментах инженера данных.
Читайте также
Следующий шаг
Если хотите разобраться в теме глубже, посмотрите программу Data Engineer для начинающих. Сопоставьте её с задачами, которые вы решаете на работе или хотите освоить.


