Нумерация страниц: с нуля или с единицы
· парсинг · пагинация
Есть ошибка, которую не видно в логах: запрос уходит, ответ приходит, статус 200, деньги списаны - а данные не те. Причина в одной цифре: в одних сервисах выдачи первая страница называется нулевой, в других первой. Кто переносит код между сервисами, попадает в это регулярно, и узнаёт об этом не из ошибки, а из отчёта, в котором позиции поехали ровно на десять строк.
Кто как считает
Единого стандарта нет. Отсчёт задал Яндекс XML, за ним пошли совместимые сервисы - но не все и не везде.
| Сервис | Яндекс | |
|---|---|---|
| Яндекс 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=1, имея в виду позиции 1–10 - сервис отдаёт вторую страницу, позиции 11–20
- ответ валидный, статус 200, списывается обычная цена
- сайт, стоявший на 7-м месте, в отчёте не находится вовсе
Дальше начинается поиск несуществующей проблемы: проверяют регион, проверяют домен, грешат на «нестабильную выдачу». А сдвиг ровно на одну страницу, и он в каждой строке отчёта.
Обратный случай мягче, но тоже неприятен: код, написанный под нумерацию с нуля, на сервисе
с нумерацией от единицы попросит page=0. Одни сервисы вернут ошибку, другие тихо
подставят первую страницу - и тогда всё будет работать до тех пор, пока кто-нибудь не начнёт
листать глубже.
Параметр page_base
Чтобы не заставлять переписывать чужой код, нумерация у нас переключается параметром запроса.
page_base=0- по умолчанию. Первая страница -page=0page_base=1- первая страница -page=1, аpage=0возвращает ошибку 37
Работает в 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. У последних нумерация задана поисковой
системой, а не сервисом, расхождения между сервисами там нет и переключать нечего:
p- номер страницы с нуля, всегдаstart- номер результата с нуля, кратный десятиfirst- номер результата с единицы, так считает сам Bing
Максимальную глубину переключатель тоже не меняет: 20 страниц, 200 результатов, независимо от того, с какого числа считать.
Что проверить при переезде
Заодно стоит помнить, что в XML-методах страница - это не всегда десять результатов: её размер
задаёт groupby, и смещение считается как page × groupby. Так что
нумерация и размер страницы - две разные настройки, и сверять нужно обе.
- Откуда переносится код и как там нумеровались страницы Google - это самое частое место расхождения
- Совпадает ли первая страница: запросите её обоими способами и сравните первый URL в ответе
- Если в коде есть арифметика вида
page = позиция / 10, она тоже написана под конкретную нумерацию
Описание параметров - в документации. Про сам
page и про то, почему сплошную глубину лучше брать одним запросом, - в статье
про смещение выдачи.
Ключ и баланс - в личном кабинете, при регистрации
на счёт падают 10 ₽.