"mode": "catalog" — обход, которому не нужны селекторы. Вы называете адрес каталога, число страниц и поля, которые хотите видеть в таблице. Как устроен сайт — где разделы, где списки, где карточки и откуда на них берётся цена, — выясняет сам сервис, и делает это по базе знаний, а не по вашему правилу.
Селекторов, follow, next, allow и deny в этом режиме нет — и если они переданы, они не нужны. Ответ всегда 202 с идентификатором: перед обходом идёт разведка, и держать соединение ради неё незачем.
Дальше всё как у обычного задания: GET /v1/crawl/{id} — ход и срез результата, /pages — страницы, /tree — каталог деревом, /cancel — остановить. См. Задания и Дерево каталога.

Поля

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

Как проходит задание

1

Разведка

Стартовая страница читается словарём: оглавление это, список товаров или карточка. Если оглавление — обход спускается по средней ссылке на этаж ниже и смотрит снова, до трёх этажей, пока не найдёт список с ценами. Отсюда берутся формы адресов разделов и карточек и число этажей до списка. Три-четыре захода, бесплатно, языковая модель не участвует.
2

Обход по дереву

Обход идёт вширь и внутри стартового пути: раздел → его подразделы → список товаров со всеми страницами пагинации → карточки. Адреса с параметрами, кроме пагинации, не берутся: это фильтры и сортировки. Вид каждой страницы читает словарь; модель зовут только там, где он не уверен.
3

Разбор

Поля снимаются с сохранённой разметки. Сначала — память сайта, потом словарь по микроразметке и подписям, и только потом, для оставшихся страниц, модель. Одна сверка цены на сайт.
4

Сводка

Модель смотрит готовую таблицу целиком и чистит то, чего не видно на одной странице: перепутанные колонки, цену строкой, рекламный хвост. Неудача этого шага задание не роняет — несведённая таблица хуже сведённой, но лучше никакой.
Ход виден в note задания: «смотрим стартовую страницу», «смотрим раздел: …», «обход по ссылкам, глубина 3», «словарём разобрано 21 страниц без обращения к модели», «сверяем цену словаря с моделью: попытка 1».

Знакомый сайт

Разведка не повторяется, если сайт уже есть в базе знаний и отпечаток вёрстки стартовой страницы не изменился: устройство берётся из карточки сайта, и задание идёт сразу в обход. Разведать сайт заранее, без обхода, можно бесплатной ручкой /v1/crawl/probe.

Если словарь не понял стартовую страницу

Тогда обход ищет карту сайта и идёт по ней — подробнее на странице Карта сайта. Нет и карты — устройство сайта разбирает модель. Не вышло и у неё — задание завершается отказом recon_failed, и денег это не стоит.

Что читает словарь

Словарь — данные, а не код: списки ценовых слов, шумовых и служебных блоков, подписи наличия, отпечатки CMS и пороги. Он собран по выборке из сотни с лишним магазинов и утверждается человеком. По нему словарь отвечает на два вопроса. Что это за страница. По числу плиток с ценой и форме ссылок с них, по ссылкам оглавления, по хлебным крошкам и заголовку. Список отличается от карточки количеством товаров с ценой на странице, оглавление — обилием ссылок одной формы без цен, подборка и служебная страница — тем и другим вместе с тем, что описано на странице Что не каталог. Откуда взять поля. Порядок источников — от самого надёжного:
  1. ld+json с типом Product: название, цена, валюта, артикул, бренд, наличие — всё сразу;
  2. itempropprice, priceCurrency, name, sku, brand, availability;
  3. Open Graph — product:price:amount и product:price:currency;
  4. подписи: блоки, чьи классы или текст содержат ценовые слова, слова «старая цена», признаки наличия.
Микроразметка есть у большинства магазинов, и на них модель не нужна вовсе. В ответе каждой такой страницы extract_note начинается со слов «по словарю: ld+json» или «по словарю: itemprop» — видно, откуда пришло значение.

Когда зовут языковую модель

Модель — запасной судья, а не основной механизм. К ней обращаются в трёх случаях, и только в них:
Плиток с ценой мало, оглавление неявное, крошки не читаются. Модель получает текст страницы и говорит: раздел, список, карточка или не каталог. Если и она не ответила со второй попытки, страница помечается failed с кодом unread, не оплачивается и по её ссылкам обход не идёт: гадать по форме адреса здесь нельзя, именно так страницы-метки когда-то уезжали в отчёт карточками товара.
Цена в рассрочку рядом с обычной, цена за штуку и за упаковку, «от … до». Словарь честно помечает страницу спорной (ambiguous), и её поля разбирает модель.
Первой карточке, разобранной словарём, модель показывают вместе с найденной ценой и спрашивают, та ли это цена. Согласилась — остальным страницам словаря верят без сверки. Не согласилась — спорная страница уходит модели целиком, а сверка повторяется на следующей. После пяти несогласий подряд задание завершается отказом price_unconfirmed: сайт подменяет цену скриптом или защитой, и гадать за деньги нельзя. Таблица при этом не отдаётся и не оплачивается.
Страницы, которые словарь не осилил вовсе, группируются по шаблону вёрстки: модели показывают несколько образцов группы, получают правило вроде «цена лежит в meta[itemprop=price]» и применяют его к остальным страницам группы без обращений. Двести обращений превращаются в десяток.

Что именно уходит модели

Не разметка. Модель получает текст страницы — тот же, что отдаёт parreq_fetch с text: true и max_chars, — без шапки, меню и подвала, с краткой сводкой микроразметки в начале и, если в тексте цены нет, с кусками скриптов, где она лежит. По умолчанию это 6 000 знаков. Ровно эту выжимку можно посмотреть самому: /v1/parse с text: true возвращает её в поле text.
Так дешевле и точнее одновременно. Страница магазина весит сотни тысяч знаков разметки, из которых товар — несколько сотен; всё остальное только мешает модели и стоит денег. А сводка микроразметки в начале выжимки даёт ей тот же источник, которым пользуется словарь.

База знаний

То, что обход узнал о сайте, не пропадает с окончанием задания. База знаний — три слоя, и все три — данные, а не код.

Словарь

Общий для всех сайтов: ценовые слова, шум, служебные блоки, подписи наличия, отпечатки CMS, пороги. Обновляется пересчётом по выборке и утверждается человеком.

Знание о сайте

По хосту: устройство каталога, подтверждённые источники полей, формы адресов не каталога, спорные страницы, статистика прогонов и ручные правки.

Память страниц

Отпечаток товарного блока каждой собранной страницы и её поля. Повторный обход платит только за то, что изменилось.
Карточка сайта проходит состояния newwarmedlearned. Прогрев — разведка без обхода: сайт открыт, устройство и источники полей записаны, статус warmed. Первый прогон дописывает то, что подтвердил на деле, — с какого источника пришла цена и согласилась ли с ней модель, — и переводит карточку в learned. Разведка повторяется, только когда меняется отпечаток вёрстки сайта. Правки, сделанные человеком в админке, сильнее выученного: словарь и обходы не перезаписывают их, пока сайт не сменил вёрстку. Сайт, закрытый по решению модерации, получает статус blocked, и обход по нему отклоняется до старта — 403 site_blocked.
Память страниц общая для хоста, а не для ключа: если вёрстка карточки не изменилась с прошлого прогона, поля берутся из памяти без единого обращения — и такая строка не оплачивается. Сколько строк пришло из памяти, видно в note задания: «из памяти 40».

Что приходит

Каждая страница — в форме ответа Fetch. В fetch_metadata к обычным полям добавляются пометки дерева:
string
sections — оглавление каталога, subsections — оглавление внутри раздела, listing — список товаров, card — карточка, not_catalog — подборка, фильтр или служебная страница.
string
С какой страницы сюда пришли. По этому полю строки складываются в дерево.
integer
У списка — сколько всего страниц у его пагинации. По нему считается, сколько каталога осталось необойдённым.
integer
У карточки — сколько на ней торговых предложений: размеров, цветов, фасовок.
object | null
У карточки — объект с заказанными полями. У списка при cards: false{"товары": [ … ]}, по объекту на плитку. У раздела и не каталога — null.
Строки идут по дереву, а не в порядке сбора: раздел, под ним подразделы, списки и товары, потом следующий раздел. В выгрузке CSV из кабинета для этого есть колонка «уровень» — 1 раздел, 2 подраздел, 3 список, 4 товар, — по которой в Excel можно свернуть всё, кроме товаров.

Тариф

Тариф единый, и позиция в прайсе одна: Больше ничего не прибавляется: ни надбавки за обход, ни отдельной цены за разбор, ни доплаты за обращения к модели — их число вы не контролируете, и платить за него было бы нечестно. Не оплачивается:
  • разведка и прогрев, в том числе /v1/crawl/probe;
  • сверка цены и сводка таблицы — они не считаются страницами;
  • страницы, признанные не каталогом: метки, фильтры, сортировки, служебные;
  • страницы, отданные из памяти сайта: вёрстка не менялась, модель не звалась;
  • страницы, которые не взялись или не прочитались (failed);
  • задание, завершившееся отказом price_unconfirmed или recon_failed.
Проверка баланса делается до старта по верхней оценке — pages × 3, это credits_max в ответе. Списание — в конце, по числу вправду доставленных страниц каталога. Прогон, запущенный из кабинета в ночное окно, дешевле на 20% — см. Crawler в кабинете.
Свой обход считается иначе — надбавкой сверх цены страницы. Сравнение и арифметика с примерами — на странице Цена обхода.

Отказы и неполные итоги

Итог всегда называет числа: «собрано 25 страниц, осталось необойдённых 234 — сайт больше оплаченного объёма». Молчаливое «готово» на трёх страницах из двадцати пяти было бы худшим из возможных отчётов. Остальные коды — общие для обхода, они на странице Ошибки.

Дальше

Разведка сайта

Узнать устройство и объём до запуска — бесплатно.

Разбор одной страницы

Проверить, что видит словарь на конкретной странице.

Что не каталог

Метки, фильтры и подборки: почему они отсеиваются и как это запоминается.

Crawler в кабинете

То же самое по расписанию, с письмом о завершении и ночной скидкой.