Нумерация страниц: с нуля или с единицы

· парсинг · пагинация

Есть ошибка, которую не видно в логах: запрос уходит, ответ приходит, статус 200, деньги списаны - а данные не те. Причина в одной цифре: в одних сервисах выдачи первая страница называется нулевой, в других первой. Кто переносит код между сервисами, попадает в это регулярно, и узнаёт об этом не из ошибки, а из отчёта, в котором позиции поехали ровно на десять строк.

Кто как считает

Единого стандарта нет. Отсчёт задал Яндекс XML, за ним пошли совместимые сервисы - но не все и не везде.

Сервис Яндекс Google
Яндекс XML (Search API) с 0 -
XMLStock с 0 с 0
XMLRiver с 0 с 1
JSON SEO с 0 с 0

Формулировка XMLRiver прямая: «Заметьте, что первая страница в Яндексе имеет номер 0, а в Google - 1». То есть внутри одного сервиса нумерация разная в зависимости от поисковой системы. XMLStock в обеих документациях пишет одинаково: «Нумерация начинается с нуля (первой странице соответствует значение „0“)».

Чем это опасно

Тем, что расхождение не выглядит как ошибка. Разберём на примере.

Скрипт мониторинга написан под XMLRiver и снимает Google. Первая страница у него - page=1. Вы переносите его на сервис с нумерацией от нуля, ничего не меняя. Что происходит:

Дальше начинается поиск несуществующей проблемы: проверяют регион, проверяют домен, грешат на «нестабильную выдачу». А сдвиг ровно на одну страницу, и он в каждой строке отчёта.

Обратный случай мягче, но тоже неприятен: код, написанный под нумерацию с нуля, на сервисе с нумерацией от единицы попросит page=0. Одни сервисы вернут ошибку, другие тихо подставят первую страницу - и тогда всё будет работать до тех пор, пока кто-нибудь не начнёт листать глубже.

Параметр page_base

Чтобы не заставлять переписывать чужой код, нумерация у нас переключается параметром запроса.

Работает в XML-методах - /yandex/xml и /google/xml. Именно туда переезжают с XMLRiver и XMLStock, и именно там нумерация расходится. В JSON-методах (/yandex, /google, /bing) page всегда считается с нуля: своей истории у нумерации там нет, переносить неоткуда. Присланный туда page_base вернёт ошибку 422 - молча его проглотить нельзя, иначе запрос уехал бы на соседнюю страницу.

Ошибки XML-методов, как и у Яндекс XML, приходят внутри самого XML с HTTP-статусом 200: <error code="37">…</error>. Разборщики вроде Key Collector читают именно код, а не статус.

Отказ на page=0 при page_base=1 тоже намеренный: такой запрос почти всегда означает, что переключатель выставлен не тем, кто писал остальной код, и молча отдать первую страницу значило бы спрятать расхождение вместо того, чтобы его показать.

Как это выглядит

Один и тот же кусок выдачи - позиции 21–30 Google - двумя способами:

# нумерация с нуля, третья страница
curl "https://jsonseo.ru/api/google/xml?query=купить+ноутбук&page=2&key=ВАШ_КЛЮЧ"

# нумерация с единицы - как в XMLRiver
curl "https://jsonseo.ru/api/google/xml?query=купить+ноутбук&page=3&page_base=1&key=ВАШ_КЛЮЧ"

Тег page в ответе

В XML-ответе есть тег <page> с номером выданной страницы - его читают разборщики, а некоторые по нему же считают следующий запрос. Отвечать в нумерации, отличной от запроса, значило бы сдвинуть выдачу прямо в ответе, поэтому номер возвращается в той же нумерации, в которой пришёл запрос.

<!-- page_base=0 (по умолчанию), page=1 -->
<page first="11" last="20">1</page>

<!-- page_base=1, page=2 - тот же кусок выдачи -->
<page first="11" last="20">2</page>

Атрибуты first и last - абсолютные номера позиций, они от нумерации страниц не зависят и всегда считаются с единицы.

На что page_base не влияет

Только на page в XML-методах. В JSON-методах смещение задаётся или тем же page с нуля, или параметрами самих поисковых систем - p у Яндекса, start у Google, first у Bing. У последних нумерация задана поисковой системой, а не сервисом, расхождения между сервисами там нет и переключать нечего:

Максимальную глубину переключатель тоже не меняет: 20 страниц, 200 результатов, независимо от того, с какого числа считать.

Что проверить при переезде

Заодно стоит помнить, что в XML-методах страница - это не всегда десять результатов: её размер задаёт groupby, и смещение считается как page × groupby. Так что нумерация и размер страницы - две разные настройки, и сверять нужно обе.

Описание параметров - в документации. Про сам page и про то, почему сплошную глубину лучше брать одним запросом, - в статье про смещение выдачи. Ключ и баланс - в личном кабинете, при регистрации на счёт падают 10 ₽.


Читайте дальше