# Инструкция для ИИ-агента или программиста: YML-фид для импорта объявлений Этот файл — техническое задание. Его передал тебе человек, который подключает свой каталог к импорту на сайте объявлений (дальше — «площадка»). Площадка примерно раз в час скачивает YML-файл (фид) по постоянной ссылке и по нему создаёт, обновляет и снимает объявления этого человека. Твоя задача — в проекте человека сделать выгрузку такого файла, опубликовать её по постоянному адресу и проверить по правилам ниже. Правила описывают фактическую работу площадки. Всё, что здесь не названо, площадка не использует. Из фида в объявление попадают название, описание, цена, фотографии и ссылка на страницу предложения. Раздел каталога площадки и контакты задаёт человек в личном кабинете площадки: в фиде их указывать не нужно. Город объявления тоже выбирается в кабинете. Если все позиции относятся к одному городу, в фиде его не указывай. Если позиции находятся в разных городах (например, агентство недвижимости сдаёт квартиры в нескольких городах), укажи у позиции её город элементом `param name="Город"` (раздел 7): человек один раз сопоставит каждый город фида с городом площадки. Действия в личном кабинете (сохранить ссылку на фид, нажать «Проверить фид», выбрать разделы, контакты, отправить заявку) выполняет человек. Ты в кабинет не входишь. ## 1. Что должно получиться 1. Генератор фида в проекте человека: команда, скрипт или обработчик, который выгружает весь актуальный каталог в один XML-файл по правилам этого документа. 2. Постоянный адрес фида, который открывается из интернета без пароля, например `https://shop.example/export/adverts.xml`. 3. Регулярное обновление файла: по расписанию (например, раз в час) или при изменении каталога. 4. Файл подтверждения сайта в корне сайта (раздел 9). 5. Отчёт человеку (раздел 13). ## 2. Порядок работы 1. Изучи проект: где хранятся позиции (товары, объекты недвижимости, услуги), категории, цены, валюта, фотографии, адреса страниц позиций; какой у сайта публичный адрес; как в проекте запускаются задачи по расписанию. 2. Задай человеку вопросы из раздела 3 — только те, на которые проект не отвечает. 3. Напиши генератор. Данные бери из базы или API проекта, а не из HTML-страниц сайта. XML собирай библиотекой языка проекта, а не склейкой строк: так экранирование будет правильным. 4. Опубликуй файл по постоянному адресу и настрой обновление. 5. Проверь результат по чек-листу из раздела 12 и исправь всё, что не проходит. 6. Отчитайся человеку (раздел 13). ## 3. Что спросить у человека - Какие позиции выгружать: все, только в наличии, только отдельные категории. По умолчанию площадка принимает до 1000 предложений (раздел 4). Если позиций больше, нужно либо выбрать часть, либо попросить площадку увеличить лимит через форму обратной связи. - Находятся ли позиции в разных городах. Если да — где в проекте хранится город позиции: его нужно выгрузить в `param name="Город"` (раздел 7). Если нет — какой город человек выберет в кабинете для объявлений. - Название города объявления запрещено в названиях предложений (раздел 8): для позиции с городом — её города, для позиции без города — города, выбранного в кабинете. - Какую цену выгружать (обычную, со скидкой) и в какой валюте. - Имя и содержимое файла подтверждения (раздел 9). Их показывает кабинет в блоке «Подтверждение сайта» после того, как человек сохранит ссылку на фид. Если ссылки ещё нет — сначала сделай фид, потом попроси человека сохранить ссылку и передать тебе файл. ## 4. Как площадка скачивает файл - Адрес начинается с `http://` или `https://`, работает на стандартном порту (80 для HTTP, 443 для HTTPS; адреса вида `:8080` не подходят), не содержит логина и пароля, длина — до 255 символов. Секретный параметр в адресе (`?key=...`) допустим. - Сервер доступен из интернета по публичному IP-адресу. Адреса локальной сети и `localhost` запрещены. - Площадка скачивает файл обычным HTTP-клиентом, а не браузером: без JavaScript, cookies, капчи и заголовка Referer. Защита от ботов, проверка браузера, блокировка по стране или IP-адресу не должны закрывать фид, файл подтверждения и фотографии. Каждый запрос площадки несёт заголовок `User-Agent` с `PartnerImport/1.0` и адресом площадки: если защиту отключить нельзя, разреши запросы с этим значением. HTTPS-сертификат не проверяется — подойдёт любой. - Ответ — код 200 и файл целиком. Пустой ответ, страница входа, коды 4xx и 5xx — ошибка загрузки. - Перенаправлений — не больше 5. Весь запрос вместе с ними должен уложиться в 60 секунд. - Размер — до 50 МБ после распаковки. Сжатие при передаче (`Content-Encoding: gzip` и другие) поддерживается, но сам файл должен быть XML, а не архивом `.zip` или `.gz`. - Формат определяется по содержимому, а не по расширению или `Content-Type`. Рекомендуемый `Content-Type` — `application/xml` или `text/xml`. - Каждый раз площадка получает весь каталог. Выгрузка только изменений, деление на несколько файлов и постраничная выдача не поддерживаются. Позиция, которой нет в новом файле, снимается с показа. - Условные запросы. Если сервер отдал заголовок `ETag` или `Last-Modified`, следующий запрос придёт с `If-None-Match` или `If-Modified-Since`. Ответ `304 Not Modified` допустим, только если файл действительно не изменился. Статический файл на nginx или Apache отвечает правильно сам. Если файл формирует скрипт и правильный ответ 304 гарантировать нельзя, не отдавай эти заголовки совсем: ложный 304 означает, что изменения каталога не дойдут до площадки. - Лучший вариант — статический файл, который генератор пересоздаёт по расписанию: сначала пишет во временный файл в той же папке, затем переименовывает его в постоянное имя. Так площадка не получит недописанный файл. Генерация при каждом запросе рискует не уложиться в 60 секунд. Ограничения каталога: - Предложений (`offer`) — до 1000 по умолчанию. Считаются все элементы `offer`, включая снятые (`available="false"`), ошибочные и повторные. Если предложений больше лимита, весь файл отклоняется, а не обрезается. - Категорий (`category`) — до 150, включая родительские и пустые. Если больше, весь файл отклоняется. Если в магазине больше категорий, выгружай укрупнённое дерево (например, два верхних уровня), а предложению из более глубокой категории указывай в `categoryId` её ближайшую выгружаемую родительскую категорию. Состав дерева не должен зависеть от наличия товаров: категория, исчезнувшая из файла, теряет сопоставление с разделом площадки (раздел 6). - Различных городов (`param name="Город"`) среди доступных предложений — до 150. Если больше, весь файл отклоняется. ## 5. Структура файла ```xml Зоомагазин «Пример» ООО «Пример» https://shop.example/ Товары для кошек Переноски и сумки Переноска для кошки https://shop.example/products/SKU-0042 1500 RUB 10 https://shop.example/images/SKU-0042-main.jpg Новая переноска. Размер 48 × 32 × 30 см. Самовывоз. ``` Правила: - Кодировка — UTF-8 (рекомендуется) или Windows-1251, объявленная в первой строке: ``. Без объявления файл читается как UTF-8. Другие кодировки не принимаются. - XML должен быть корректным: `&`, `<` и `>` в тексте экранированы (`&`, `<`, `>`), значения атрибутов — в кавычках, управляющие символы с кодами 0x00–0x1F (кроме табуляции и переводов строк) удалены, байты — валидный UTF-8. Одна ошибка разметки отклоняет весь файл. Тексты из базы часто содержат управляющие символы и незакрытые HTML-теги — очищай их или передавай HTML через CDATA (раздел 7, `description`). - Запрещены ``, объявления сущностей и XInclude: с ними весь файл отклоняется. Не добавляй строку ``, которую ставят многие старые генераторы YML. - Корень — один элемент `yml_catalog`. В нём ровно один `shop`. В `shop` — не больше одного `categories` и одного `offers`, прямыми потомками. `offers` обязателен: без него файл отклоняется. `categories` обязателен, если в `offers` есть хоть одно предложение без `available` или с `available="true"`: без него или с пустым `categories` такой файл тоже отклоняется. Пустой `offers` или `offers` только из предложений с `available="false"` площадка примет и без категорий: так снимаются товары. Но проще и надёжнее выгружать `categories` всегда. `category` стоит только прямо внутри `categories`, `offer` — только прямо внутри `offers`. В других местах файла элементы `shop`, `categories`, `offers`, `category` и `offer` недопустимы — иначе весь файл отклоняется. - Атрибут `yml_catalog@date` необязателен. Если указываешь его — с часовым поясом, как в примере; без пояса будет предупреждение. Элементы внутри `shop`: - `url` — обязателен. Абсолютный адрес сайта человека, например `https://shop.example/`: схема http или https, без номера порта, без логина и пароля, без пробелов, кавычек, `<`, `>` и `\`, до 255 символов. Это «сайт источника»: в его корне размещается файл подтверждения (раздел 9), и на него должны вести ссылки `offer/url`. Сам фид и фотографии могут лежать на других доменах. Без корректного `shop/url` весь файл отклоняется. - `name`, `company` — необязательны: названия магазина и компании, человек видит их в кабинете. Длиннее 255 символов обрезаются. - `currencies` — не нужен. Если он есть, площадка пропускает его без предупреждения; курсы валют не применяются. - Любой другой элемент внутри `shop` (`platform`, `version`, `email`, `delivery-options` и т. п.) пропускается с предупреждением в отчёте. ## 6. Категории - `id` — обязателен: только цифры, целое число больше 0, не длиннее 18 цифр, уникальное в файле. Нечисловой, нулевой или пустой `id`, повтор `id`, неверный `parentId` — весь файл отклоняется. - `parentId` — необязателен: `id` родительской категории из этого же файла. У корневой категории `parentId` нет или он равен `0`. Ссылка на отсутствующую категорию и циклы недопустимы — весь файл отклоняется. - Текст элемента — название категории, до 255 символов. Человек видит его в кабинете, когда сопоставляет категории фида с разделами площадки. В объявления название категории не попадает. - Каждая категория, на которую ссылается `offer/categoryId` предложения к публикации (без `available` или с `available="true"`), должна быть в `categories`. У предложений с `available="false"` `categoryId` не сверяется (раздел 7). - `id` категорий должны быть постоянными: бери их из базы проекта, а не нумеруй по порядку. Человек сопоставляет категории с разделами площадки по `id`. Категория, исчезнувшая из файла, теряет сопоставление, а категорию с новым `id` придётся настраивать заново. Исключение — файл совсем без категорий (пустой или отсутствующий `categories` при одних снятых предложениях): все сопоставления сохраняются до возвращения товаров. Поэтому, снимая товары, не сокращай `categories`: выгружай одно и то же дерево категорий, в том числе категории, в которых сейчас нет предложений. - Предложения категории без выбранного раздела не публикуются. Когда после одобрения заявки в такой категории появляются предложения, площадка пишет владельцу подключения письмо, и человек выбирает раздел или «Не импортировать» в кабинете. - Каждая категория сопоставляется отдельно: от родителя раздел не наследуется. Предложение может ссылаться на категорию любого уровня. ## 7. Предложения Атрибуты `offer`: - `id` — обязателен. От 1 до 80 символов после обрезки пробелов по краям. Постоянный: по нему площадка при следующих загрузках находит то же объявление. Регистр и ведущие нули значимы: `SKU-42`, `sku-42` и `SKU-0042` — три разных предложения. Бери артикул или первичный ключ из базы, а не номер строки выгрузки. Пустой или слишком длинный `id` — ошибка предложения. - `available` — `true` или `false`, строчными буквами. Без атрибута предложение считается доступным, а в отчёте появляется общее предупреждение. Пустое значение, `True`, `1`, `yes` — ошибка предложения. Указывай атрибут всегда. - `type` — не указывай для обычного предложения: название берётся из `name`. Значение `vendor.model` означает, что название составляется из `typePrefix`, `vendor` и `model`. Любой другой тип (`books`, `medicine`, `event-ticket` и прочие) — ошибка предложения. Площадка читает только прямых потомков `offer`. Значения обрезаются по краям. - `name` — обязателен для обычного предложения. Становится названием объявления. Правила текста — раздел 8. - `typePrefix`, `vendor`, `model` — только для `type="vendor.model"`. Название объявления — `typePrefix vendor model` через пробел. `vendor` и `model` обязательны, `typePrefix` — нет. Без `vendor` или `model` — ошибка предложения. - `categoryId` — обязателен: `id` категории из `categories`. Нечисловое значение или категория, которой нет в файле, — ошибка предложения. Если `categoryId` нет или он пустой, предложение не будет опубликовано. - `description` — обязателен: текст объявления. HTML допустим — экранированный или внутри ``; CDATA надёжнее. Площадка удаляет `script` и `style` вместе с содержимым, превращает `p`, `div`, `br`, `li`, `h1`–`h6`, `tr`, `table`, `ul`, `ol`, `blockquote`, `pre`, `hr`, `dl`, `dt`, `dd` в переводы строк, ячейки `td` и `th` — в пробелы, остальные теги удаляет, HTML-сущности раскрывает, пустые строки убирает. Пустой после очистки текст — предложение не будет опубликовано. Необработанное описание больше 10 МБ отклоняет весь файл. - `price` — необязателен. Неотрицательное десятичное число с точкой: `1500`, `1499.90`. Без пробелов, запятых, знака валюты и экспоненты, иначе ошибка предложения. Дробная часть округляется до целого, половина — вверх: `1499.49` → 1499, `1499.50` → 1500. После округления — не больше 4294967295. Отсутствующая, пустая или нулевая цена означает «договорная»; пометку «бесплатно» фид не ставит. - `currencyId` — необязателен, регистр не важен. Допустимы `RUB` (и `RUR` как то же самое), `USD`, `EUR`, `AMD`, `KZT`, `GEL`, `BYN`, `UAH`, `AZN`, `KGS`, `RSD`. Без `currencyId` — рубли. Другая валюта — ошибка предложения. Цена не пересчитывается. - `url` — необязателен, но желателен. Абсолютный адрес страницы предложения: http или https, до 255 символов, без пробелов и обратной косой черты, без логина и пароля. Домен — тот же, что в `shop/url`, его поддомен или вариант с `www` и без него. Иначе — ошибка предложения. В объявлении ссылка выводится строкой «Веб-сайт» и считается способом связи: без неё новое объявление создаётся, только если человек выбрал в кабинете телефон, email или Telegram. - `picture` — необязателен, повторяется. Абсолютные адреса изображений в нужном порядке; первое — главное. Пустые элементы пропускаются, берутся первые 5 адресов, остальные игнорируются с предупреждением. Подробно — раздел 10. - `param name="Город"` — необязателен: город предложения, например `Казань`. Нужен, только когда предложения находятся в разных городах. Атрибут `name` сравнивается без учёта регистра и пробелов по краям, атрибут `unit` не учитывается. Значение обрезается по краям, внутренние пробелы схлопываются; пустое значение равнозначно отсутствию элемента. Регистр и буква «ё» город не различают: «Казань», «казань» и «КАЗАНЬ» — один город. Город — до 255 символов, иначе ошибка предложения. Два и более непустых элемента «Город» в одном предложении — ошибка предложения. Пиши официальное название города, лучше по-русски, без «г.», района и региона: «Санкт-Петербург», а не «СПб» или «Питер». Такой город человеку проще сопоставить, а если название однозначно совпадёт с городом из справочника площадки, кабинет предложит этот город кнопкой «Подставить»: человек проверит страну и регион и сохранит настройки. Предложение с `available="false"` площадка читает почти без проверок: нужен корректный `id`, остальные поля, включая город, не проверяются. Существующее объявление снимается с показа, новое не создаётся. Как работает город: - Город фида площадка сама с городом площадки не сопоставляет: названия городов повторяются, в том числе в пределах одного региона. Каждый город фида человек один раз сопоставляет в кабинете, в таблице «Города фида», после нажатия «Проверить фид». - Предложение с городом, которому человек ещё не выбрал город площадки, не публикуется (ошибка «Городу предложения не выбран город сайта»). Заявка на импорт не отправляется, пока есть такие города с предложениями в импортируемых категориях. - Если после одобрения заявки в фиде появится такой город, площадка пришлёт владельцу подключения письмо со списком новых городов и категорий без выбора. Поэтому, начиная передавать `param name="Город"` в уже подключённом фиде, предупреди человека: пока он не выберет города в кабинете, предложения с ними не публикуются, а прежние объявления не обновляются. - Предложение без города публикуется в городе по умолчанию, выбранном в кабинете. Если в фиде есть предложения и с городом, и без него, отчёт предупреждает о числе предложений без города. Фид совсем без городов — обычный случай одного города, предупреждения нет. - Выбор города площадки сохраняется, даже если город временно исчезнет из фида: когда предложения этого города вернутся, они опубликуются без новой настройки. - Контакты в объявлениях общие для всех городов — из профиля владельца. Телефоны по городам в фиде не передаются. Всё остальное внутри `offer` (прочие `param`, `oldprice`, `vendorCode`, `barcode`, `delivery`, `pickup`, `sales_notes`, `country_of_origin` и т. п.) пропускается, а имена элементов попадают в предупреждение отчёта. Это не ошибка, но лишние элементы лучше не выгружать. Если в характеристиках есть важное для покупателя — размеры, состав, комплектация, — перенеси это в `description` текстом. ## 8. Правила для названия и описания Площадка проверяет название и описание по тем же правилам, что и объявления, поданные вручную. Предложение с нарушением пропускается, причина видна в отчёте. Тексты не обрезаются и не исправляются автоматически. Важно: эти правила проверяются только при загрузках после одобрения заявки. Кнопка «Проверить фид» в кабинете их не проверяет. Она находит ошибки структуры файла и полей, которые отклоняет разбор (`id`, `available`, `type`, название, формат `price`, `categoryId`, город), а также пустое описание и отсутствующий `categoryId` у доступного предложения. Валюту, длину и домен `offer/url`, предел цены и правила текстов видят только загрузки после одобрения — проверь их сам до сдачи работы (раздел 12, пункты 8 и 10). - Название — от 1 до 150 символов. Описание — от 1 до 5000 символов после очистки HTML. - Нет ссылок: любые `http://`, `https://` или `www.` в тексте. Ссылку на страницу предложения передавай только в `offer/url`. - Нет адресов email. - Нет номеров телефонов. Телефоном считается ряд из 11 цифр, который начинается с `7`, `8` или `+7`, а также `+374` и ещё 8 цифр, если между цифрами нет букв (пробелы, скобки, точки, дефисы, запятые и косые черты не мешают) и ряд не стоит вплотную к другим цифрам или буквам. Под это правило попадают и артикулы вида `8-123-456-78-90`. Контакты площадка добавляет в объявление сама из настроек кабинета. - Нет «слов» из 30 и более символов без пробелов — считаются любые символы, кроме пробельных, включая знаки препинания. Длинные артикулы, перечисления через косую черту (`кошек/собак/хомяков/попугаев`) и склеенные слова разделяй пробелами. - В названии нет названия города объявления в любой форме — города, выбранного в кабинете для города предложения, или города по умолчанию для предложения без города: «Москва», «Москвы», «Москве». Проверка не различает регистр, считает латинские буквы-двойники кириллическими и ищет название и внутри других слов. В описании город упоминать можно. - Нет нецензурной лексики и стоп-слов. Словари открыты: https://github.com/Vasiliy-Makogon/RussianBadWords — нецензурная лексика в файлах `data/profanity.php`, `data/rude.php`, `data/insults.php`, `data/anatomy.php`, стоп-слова — в каталоге `data/stop-words/`. Темы стоп-слов: алкоголь; табак, вейпы, кальяны; наркотики; оружие и средства самообороны; насилие; экстремизм; суицид; интим-услуги; казино и азартные игры; кредиты, займы, криптовалюта, страховки; рецептурные препараты и донорство; поддельные документы и дипломы; магия и гадания; пиратство и взлом; спам и мошенничество; запрещённые орудия лова; даркнет и названия даркнет-площадок (среди них есть обычные слова, например `empire`, `evolution`, `hydra`). Слово ищется целиком в любой форме из словаря, без учёта регистра, буквы «ё», латинских двойников и повторов букв; слово через дефис проверяется и по частям. Если такое слово — часть названия бренда или модели, обсуди с человеком, как переформулировать. Повторяющиеся названия и описания у разных предложений допустимы. Недвижимость. Отдельного формата для недвижимости нет: у объявления площадки нет полей комнат, площади, этажа, периода цены, залога и комиссии. Пиши их текстом: - в название — тип объекта, число комнат, площадь и этаж, например «2-комнатная квартира, 54 м², 5/9 этаж». Название города в название не пиши — оно запрещено правилом выше; город передаётся элементом `param name="Город"`; - в описание — период цены («45 000 ₽ в месяц»), коммунальные платежи («плюс счётчики» или «включены»), залог, комиссию, срок аренды, адрес и прочие подробности; - в `price` — число без периода: `45000`. Период цены площадка не хранит, поэтому он обязательно указывается в описании; - раздел каталога площадки для аренды и продажи выбирает человек в кабинете для каждой категории фида: держи аренду и продажу в разных категориях фида. Пример фида агентства с квартирами в двух городах — раздел 16. ## 9. Подтверждение сайта Площадка проверяет, что фид публикует владелец сайта из `shop/url`. После сохранения ссылки на фид кабинет показывает файл вида `partner-verification-<метка>.txt`, где метка — 32 шестнадцатеричных символа, а содержимое файла — та же метка. - Размести файл в корне сайта из `shop/url`, чтобы он открывался по адресу `<схема и домен из shop/url>/partner-verification-<метка>.txt`, например `https://shop.example/partner-verification-0123456789abcdef0123456789abcdef.txt`. Порт площадка тоже берёт из `shop/url`, а обращается только к стандартным портам (раздел 4), поэтому с нестандартным портом в `shop/url` сайт не подтвердится. - Ответ — код 200, тело — ровно метка; пробелы и переводы строк по краям допустимы. Размер ответа — не больше 1 КБ, время — до 10 секунд. - Перенаправление допустимо только в пределах того же сайта: между http и https и между вариантами с `www` и без него. Перенаправление на другой домен или поддомен проверку не проходит. - Не удаляй файл после подтверждения. Если человек перевыпустит метку или в `shop/url` появится другой домен, понадобится новый файл. - Если файла подтверждения ещё нет, всё равно сделай фид: человек получит имя файла после сохранения ссылки и передаст его тебе. ## 10. Фотографии - Абсолютные адреса http или https; относительные пути (`/images/1.jpg`) не загружаются. Те же сетевые правила, что для фида (раздел 4): стандартный порт, публичный адрес, без пароля и защиты от ботов. Защита от прямых ссылок по заголовку Referer не должна блокировать запросы без этого заголовка. - Форматы — JPEG, PNG или WebP; определяются по содержимому, а не по расширению. GIF, SVG и прочие не принимаются. - Размер одного файла — до 15 МБ, разрешение — до 25 мегапикселей (ширина × высота), ответ сервера — до 10 секунд. - Площадка запоминает фотографию по адресу и повторно её не скачивает. Чтобы заменить изображение, измени адрес: имя файла или параметр вроде `?v=2`. Новый файл по старому адресу площадка не заметит. - Порядок адресов задаёт порядок фотографий. Адрес, исчезнувший из первых пяти, отвязывает свою фотографию от объявления. - Сбой фотографии — не ошибка предложения: объявление публикуется без неё, а площадка повторяет попытку примерно раз в сутки, пока адрес остаётся в фиде. ## 11. Обновление, снятие и возврат предложений - Изменил цену, текст или фотографии — оставь прежний `id`: площадка обновит то же объявление, его адрес и дата публикации сохранятся. Обновление не поднимает объявление в списке. - Новая позиция — новый `id`. Никогда не меняй `id` существующей позиции и не отдавай `id` снятой позиции другой: новый `id` создаёт новое объявление, а старое снимается. - Временно нет в наличии — `available="false"` или убери предложение из файла; позиция снята с продажи навсегда — убери её из файла. В обоих случаях объявление скрывается и хранится 180 дней: если предложение вернётся с тем же `id`, вернётся прежнее объявление. Через 180 дней объявление удаляется. Учти, что предложения с `available="false"` занимают место в лимите. - Пустой каталог `` снимает с показа все объявления. Если элемента `offers` в файле нет совсем, весь файл отклоняется, и объявления не меняются. Сопоставления категорий при снятии сохраняются, только если в файле всё дерево `categories` или категорий нет совсем (раздел 6). - Если `id` повторяется, все предложения с этим `id` пропускаются, а прежнее объявление остаётся без изменений. - Если у какого-то предложения `id` пустой или длиннее 80 символов, в этой загрузке площадка не снимает предложения, исчезнувшие из файла. - Объявление, которое удалил администратор площадки, по тому же `id` заново не создаётся; причина видна в отчёте. - Ошибка в новой версии предложения не портит объявление: оно остаётся с прежними данными до первой успешной загрузки исправленной версии. ## 12. Чек-лист самопроверки Выполни перед отчётом. Каждый пункт — проверка результата, а не намерение. 1. Фид скачивается без cookies и авторизации так же, как его запрашивает площадка, — с переходами по перенаправлениям и с её `User-Agent`: `curl -sS -L --max-redirs 5 -A 'Mozilla/5.0 (compatible; PartnerImport/1.0)' -o feed.xml -w '%{http_code} %{size_download} %{time_total}\n' '<адрес фида>'` — код 200, размер до 50 МБ, время вместе с перенаправлениями заметно меньше 60 секунд. Запрос сделан не изнутри сервера проекта, а из внешней сети: так видно, что фид доступен из интернета. 2. Файл разбирается XML-парсером без ошибок (например, `xmllint --noout feed.xml`). В нём нет ``. - «В файле несколько разделов shop.» — оставь один `shop`. - «В файле отсутствует раздел offers с предложениями.» — добавь `offers` в `shop`. - «В файле нет категорий: раздел categories отсутствует или пуст. …» — добавь `categories` в `shop` или заполни его, если он выгружается пустым: в нём должны быть все категории, на которые ссылаются `categoryId`. - «В разделе shop отсутствует корректный HTTP- или HTTPS-адрес сайта источника в поле url.» — исправь `shop/url`. - «Число предложений в фиде: N, разрешено не более M.» — уменьши выгрузку или договорись о лимите. - «Количество категорий превышает допустимое» — сократи дерево категорий до 150. - «Различных городов в предложениях: N, допускается не более M.» — сократи число городов фида. - «У категории не указан или недопустим номер …», «Идентификатор категории N повторяется», «У категории N указан родитель, которого нет в фиде», «В дереве категорий найден цикл» — исправь `categories`. - «Сайт источника не подтверждён. Причина: …» — раздел 9. Ошибки предложения, которые показывает и «Проверить фид»: - «Недопустимое значение available» — только `true` или `false`. - «Неподдерживаемый тип предложения» — убери `type` или используй `vendor.model`. - «Не заполнено название предложения в поле name», «Для типа vendor.model заполните поля vendor и model». - «Некорректная цена» — формат `price`. - «Идентификатор предложения id отсутствует или превышает 80 символов», «Идентификатор предложения повторяется». - «Категория N не найдена в разделе categories». - «Категории предложения не настроено соответствие» — у предложения нет `categoryId`. В отчёте загрузки после одобрения та же ошибка бывает и тогда, когда человек ещё не выбрал раздел для этой категории в кабинете. - «Не заполнено описание предложения в поле description». - «Элемент «Город» (param name="Город") указан в предложении несколько раз.» — оставь у предложения один город. - «Название города «…» длиннее 255 символов.» — сократи название города. Ошибки предложения, которые появляются только в отчётах загрузок после одобрения заявки: - «Цена превышает максимально допустимое значение» — после округления `price` не больше 4294967295 (раздел 7). - «Неизвестная валюта» — `currencyId` из списка раздела 7. - «Ссылка на страницу предложения превышает допустимую длину», «Ссылка на страницу предложения должна вести на подтверждённый сайт магазина или его поддомен» — `offer/url`. - «Городу предложения не выбран город сайта» — человек ещё не сопоставил этот город фида с городом площадки в кабинете; фидом не исправляется, если город указан верно. - «Объявление не прошло проверки: …» — правила раздела 8 или настройки кабинета (способ связи, раздел площадки). Причина указана после двоеточия. - «Создание объявления по этому предложению запрещено администрацией» — решение площадки, фидом не исправляется. Предупреждения: - «Неподдерживаемые элементы пропущены: …» — элементы, которых нет в этом документе; можно не выгружать. - «Число предложений без атрибута available: N» — добавь `available`. - «Предложений без элемента «Город»: N» — эти предложения публикуются в городе по умолчанию; если они относятся к другим городам, добавь им `param name="Город"`. - «Дата фида указана без часового пояса» — добавь пояс в `yml_catalog@date` или убери атрибут. - «Из N фотографий в файле берутся только первые 5», «Не удалось скачать фотографию …», «Фотография … не принята», «Фотография … превышает допустимый размер в мегапикселях» — раздел 10. - «Объявления по предложениям, удалённым из файла, в этом запуске не скрываются» — есть предложения с пустым или слишком длинным `id`. ## 15. Пример фида магазина Все поддерживаемые поля, кроме города: город показан в примере раздела 16. ```xml Зоомагазин «Пример» ООО «Пример» https://shop.example/ Товары для кошек Переноски и сумки Когтеточки Переноска для кошки https://shop.example/products/SKU-0042 1500 RUB 10 https://shop.example/images/SKU-0042-main.jpg https://shop.example/images/SKU-0042-side.jpg Новая переноска.

Размер 48 × 32 × 30 см. Самовывоз.

]]>
Когтеточка ПримерДом Floor Tower S https://shop.example/products/SKU-0107 3490.90 RUB 20 https://shop.example/images/SKU-0107.jpg Когтеточка-стойка, обмотка из натурального сизаля. Высота 60 см. Мяч для кошек, 2 шт. 1 Два мяча с колокольчиком. Лежанка для кошки 1
``` ## 16. Пример фида агентства недвижимости с городами Предложения в двух городах: город передан элементом `param name="Город"`, в названиях городов нет, период цены и условия аренды — в описании (раздел 8). Объект, сданный арендатору, снят атрибутом `available="false"`. ```xml Агентство «Пример» ООО «Пример недвижимость» https://agency.example/ Аренда Квартиры в аренду Комнаты в аренду 2-комнатная квартира, 54 м², 5/9 этаж https://agency.example/objects/A1245 45000 RUB 11 Казань https://agency.example/img/A1245-1.jpg https://agency.example/img/A1245-2.jpg Сдаётся на длительный срок: 45 000 ₽ в месяц плюс счётчики.

Залог 45 000 ₽, комиссия агентства 50%. Мебель и бытовая техника, рядом метро.

]]>
Комната 18 м², 2/5 этаж https://agency.example/objects/A1301 15000 RUB 12 Казань https://agency.example/img/A1301-1.jpg Сдаётся на длительный срок: 15 000 ₽ в месяц, коммунальные платежи включены. Залог 10 000 ₽, без комиссии. 1-комнатная квартира, 38 м², 3/10 этаж https://agency.example/objects/S0310 25000 RUB 11 Самара https://agency.example/img/S0310-1.jpg Сдаётся на длительный срок: 25 000 ₽ в месяц плюс счётчики. Залог 25 000 ₽, комиссия агентства 30%. Студия 26 м², 8/17 этаж 11 Самара
```