Пошаговые инструкции Для начинающих 14 мин

RSS в n8n: как прочитать ленту и подготовить дайджест

Прочитайте RSS, проверьте записи и отсортируйте новости по дате. 12 шагов и готовый workflow с предпросмотром без отправки и публикации.

n8n дайджест RSS

RSS — это лента записей с заголовками, датами и ссылками. n8n может прочитать её без копирования новостей вручную. Но прочитать ленту ещё не значит получить готовый дайджест: записи бывают без даты, с повторными ID или в неожиданном порядке. Соберём проверяемый предпросмотр, который останавливается на таких ошибках.

Результат инструкции

Получим три записи из собственной учебной RSS-ленты ezGPT. Штатный RSS Read превратит их в items, Code проверит обязательные поля, Sort поставит более новые записи первыми. Последний Code соберёт один JSON: status needs_review, count 3, массив entries, approved false и action_performed false.

Это подготовка данных для ручной редакторской проверки, не готовая новостная статья и не AI-выжимка. Модель, API-ключ и платная подписка не нужны. Записи вымышлены, даты зафиксированы для воспроизводимости. Адреса example.invalid внутри записей — намеренные учебные заглушки: открывать их бессмысленно. RSS Read загружает XML ленты, но не переходит по ссылкам каждой новости.

Что понадобится

  • Работающий n8n и доступ к созданию отдельного workflow. Проверено на n8n 2.42.4, RSS Read версии 1.2 и Sort версии 1.
  • Доступ из n8n к HTTPS-файлу учебной ленты. Сервер, на котором работает n8n, должен сам видеть ezgpt.ru; открытая страница в вашем браузере этого не доказывает.
  • Новый учебный workflow. Рабочие рассылки, каналы и сайт к нему подключать не нужно.

Установить n8n локально через Docker

Шаг 1. Импортируйте готовую схему

Скачать n8n-rss-digest-preview.json

Создайте новый workflow. В меню редактора выберите Import from File и загрузите JSON. Файл не содержит credentials и ID чужого workflow, схема неактивна. После импорта должны появиться пять соединённых узлов:

text
Manual Trigger → Read Demo Feed → Check Feed → Sort News → Digest Preview

Read Demo Feed — штатный RSS Read. Check Feed и Digest Preview — Code. Sort News — Sort. Если собираете вручную, сохраните эти имена: итоговая проверка обращается к Check Feed по имени. Не добавляйте Schedule Trigger, отправку писем и публикацию, пока проверяете прототип.

Шаг 2. Проверьте учебный XML

Открыть учебную RSS-ленту ezGPT

В XML есть rss version 2.0, channel и три item. У каждой записи заданы guid, title, link, pubDate и description. В guid стоит isPermaLink false: это строковый идентификатор demo-001, а не адрес страницы. Вторая запись в файле новее первой — это специально, чтобы проверить сортировку.

xml
<item>
  <guid isPermaLink="false">demo-002</guid>
  <title>Учебная новость: проверка RSS</title>
  <link>https://example.invalid/rss-demo-002</link>
  <pubDate>Fri, 16 Oct 2026 08:00:00 GMT</pubDate>
  <description>Проверяем заголовок и дату.</description>
</item>

Если браузер показывает XML как дерево или предлагает скачать файл, это нормально. Если открывается страница входа, HTML ошибки или пустой файл, сначала решите проблему с доступом. Сам пример работает с публичным XML, без авторизации.

Шаг 3. Настройте RSS Read

Откройте Read Demo Feed. В URL вставьте https://ezgpt.ru/storage/article-files/ezgpt-rss-demo.xml. Это адрес самой ленты, не главная страница сайта. В Options оставьте Ignore SSL Issues выключенным. Custom Fields не заполняйте: используем стандартные поля.

В Settings включите Always Output Data только у Read Demo Feed. Пустая RSS-лента иначе может дать ноль items, и следующий Code вообще не запустится. С включённой настройкой до проверки дойдёт пустой объект, который превратим в явную ошибку feed_empty.

Для всех узлов оставьте On Error: Stop Workflow. Continue On Fail, Retry On Fail и Execute Once не включайте. Проблемы сертификата не нужно скрывать отключением проверки TLS. В этом примере не тестируется обход сетевых ограничений или доступ к защищённым лентам.

Шаг 4. Выполните чтение и проверьте поля

Запустите workflow от Manual Trigger и посмотрите Output узла Read Demo Feed. Ожидаются три items, а не один item с массивом news. Первый item должен содержать такие данные:

json
{
  "title": "Учебная новость: проверка RSS",
  "link": "https://example.invalid/rss-demo-002",
  "pubDate": "Fri, 16 Oct 2026 08:00:00 GMT",
  "content": "Проверяем заголовок и дату.",
  "contentSnippet": "Проверяем заголовок и дату.",
  "guid": "demo-002",
  "isoDate": "2026-10-16T08:00:00.000Z"
}

Штатный парсер добавил isoDate с UTC-временем и contentSnippet с текстовым описанием. pubDate остался исходной строкой. В следующем узле используем isoDate, чтобы не сортировать английские названия дней недели. contentSnippet — описание из ленты после удаления разметки, не полный текст статьи и не пересказ от модели.

Поле RSS Read Во что преобразуем Правило примера
guid id Непустая строка, без повторов
title title Непустой текст, до 200 символов
link link Учебный адрес example.invalid
isoDate published_at UTC-строка с датой и временем

Дополнительно contentSnippet переносится в excerpt: непустая строка не длиннее 1000 символов. Остальные поля парсера в предпросмотр не переносим. Для реальной ленты отсутствие описания может быть допустимым, но здесь договор намеренно строгий.

Шаг 5. Добавьте проверку записей

В Check Feed выберите Mode: Run Once for All Items, Language: JavaScript. Вставьте весь код:

javascript
const items = $input.all();
if (!items.length || (items.length === 1 && !Object.keys(items[0].json).length)) {
  throw new Error('feed_empty');
}
if (items.length > 20) throw new Error('feed_too_many_items');
const ids = new Set();
const links = new Set();
return items.map(({ json: row }) => {
  const text = key => {
    const value = row[key];
    if (typeof value !== 'string' || !value.trim()) throw new Error(key + '_required');
    return value.trim();
  };
  const id = text('guid');
  const title = text('title');
  const link = text('link');
  const date = text('isoDate');
  const excerpt = text('contentSnippet');
  if (title.length > 200 || excerpt.length > 1000) throw new Error('feed_text_too_long');
  if (!link.startsWith('https://example.invalid/') || !/^rss-demo-\d{3}$/.test(link.slice('https://example.invalid/'.length))) {
    throw new Error('feed_link_not_allowed');
  }
  if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(date) || !Number.isFinite(Date.parse(date))) {
    throw new Error('feed_date_invalid');
  }
  if (ids.has(id) || links.has(link)) throw new Error('feed_duplicate');
  ids.add(id);
  links.add(link);
  return { json: { id, title, link, published_at: date, excerpt } };
});

Проверка принимает от 1 до 20 записей. Двадцать — наше учебное ограничение после чтения, а не предел RSS Read и не защита загрузки от большого XML. Заголовки и описания очищаются от внешних пробелов. Повтор ID или ссылки завершает запуск с feed_duplicate; записи не склеиваются и не удаляются молча.

Разрешён только точный учебный префикс https://example.invalid/ и путь rss-demo- с тремя цифрами. В реальной задаче замените правило согласованным списком доменов источников, а не убирайте проверку целиком. Этот Code не переходит по ссылкам.

Даты берутся из isoDate, уже созданного парсером. Код проверяет форму UTC-строки и возможность прочитать её, но не доказывает правильность исходной даты издателя. Некорректную календарную дату некоторые парсеры могут нормализовать. Для реальных новостей отдельно проверяют исходную дату, часовой пояс и актуальность.

Шаг 6. Отсортируйте новости

В Sort News выберите Type: Simple. Добавьте два поля в таком порядке: published_at — Descending, затем id — Ascending. Остальные настройки оставьте исходными.

Сначала сравниваются даты: более поздняя идёт выше. При одинаковой дате сравнивается ID, чтобы результат не зависел от исходного порядка XML. Здесь даты приведены парсером к одной UTC-форме. Не подставляйте вместо published_at исходную строку pubDate или даты с разными смещениями без нормализации.

Позиция ID published_at
1 demo-001 2026-10-16T09:00:00.000Z
2 demo-002 2026-10-16T08:00:00.000Z
3 demo-003 2026-10-15T15:00:00.000Z

Выполните узел и сверьте порядок с таблицей. Это отбор по времени публикации внутри файла, не фильтр «за последние сутки». Три записи останутся в результате и завтра: текущая дата в схеме не используется.

Шаг 7. Соберите предпросмотр

В Digest Preview выберите Run Once for All Items, JavaScript и вставьте:

javascript
const source = $('Check Feed').all().map(item => item.json);
const entries = $input.all().map(item => item.json);
const expected = [...source].sort((a, b) => b.published_at.localeCompare(a.published_at) || a.id.localeCompare(b.id));
if (JSON.stringify(entries) !== JSON.stringify(expected)) throw new Error('feed_order_mismatch');
return [{ json: {
  status: 'needs_review',
  count: entries.length,
  entries,
  approved: false,
  action_performed: false,
} }];

Последний узел заново вычисляет ожидаемый порядок по проверенным записям и сравнивает его с выходом Sort. Так ошибку Descending/Ascending не получится скрыть обычным успешным статусом. В результат переносится весь проверенный список, сокращения до топ-3 здесь нет.

needs_review и approved false — поля данных для человека, а не действующий механизм согласования. В этой схеме физически нет узла отправки или публикации. Перед добавлением таких действий нужны отдельная проверка прав, подтверждение редактора и журнал результата.

Шаг 8. Запустите всю цепочку

Нажмите Execute Workflow. После RSS Read, Check Feed и Sort News должно быть по три items. Digest Preview возвращает один item с таким JSON:

json
{
  "status": "needs_review",
  "count": 3,
  "entries": [
    {
      "id": "demo-001",
      "title": "Учебная новость: текст & данные",
      "link": "https://example.invalid/rss-demo-001",
      "published_at": "2026-10-16T09:00:00.000Z",
      "excerpt": "Это вымышленная запись, не новость редакции."
    },
    {
      "id": "demo-002",
      "title": "Учебная новость: проверка RSS",
      "link": "https://example.invalid/rss-demo-002",
      "published_at": "2026-10-16T08:00:00.000Z",
      "excerpt": "Проверяем заголовок и дату."
    },
    {
      "id": "demo-003",
      "title": "Учебная новость: черновик дайджеста",
      "link": "https://example.invalid/rss-demo-003",
      "published_at": "2026-10-15T15:00:00.000Z",
      "excerpt": "Готовим данные без отправки и публикации."
    }
  ],
  "approved": false,
  "action_performed": false
}

Проверьте count 3, порядок demo-001 → demo-002 → demo-003, слово «данные» и амперсанд в первом заголовке. approved и action_performed должны быть логическими false, не строками. Ссылки сохранились как данные; workflow не проверяет их доступность и не получает полные статьи.

Шаг 9. Добавьте временный узел для теста

Чтобы проверить ошибки, не меняя публичный XML, добавьте Code с именем Test Feed между Read Demo Feed и Check Feed. Соедините цепочку через него, выберите Run Once for All Items и JavaScript. Вставьте:

javascript
const scenario = 'empty';
const rows = $input.all().map(item => ({ ...item.json }));
if (scenario === 'empty') return [{ json: {} }];
if (scenario === 'single') return [{ json: rows[0] }];
if (scenario === 'title') rows[0].title = '';
if (scenario === 'duplicate') rows[1].guid = rows[0].guid;
return rows.map(json => ({ json }));

Test Feed нужен только для диагностики. Он изменяет копию items текущего выполнения, не XML на сайте. В готовом скачиваемом workflow этого узла нет. В строке scenario переключайте только указанные значения и каждый раз запускайте всю цепочку от начала.

Шаг 10. Проверьте пустую ленту и одну запись

Оставьте scenario empty. Ожидается feed_empty в Check Feed и отсутствие успешного Digest Preview. Это имитация пустого объекта, который Always Output Data отдаёт после действительно пустой ленты; она не проверяет сетевую доступность источника.

Замените empty на single. После запуска ожидаются count 1 и только demo-002: это первая запись исходного XML, а не самая новая из всех трёх. Сначала Test Feed оставил одну запись, и только затем Sort отсортировал оставшееся. Не путайте такое ограничение до сортировки с выбором самой новой новости.

Шаг 11. Проверьте пропуск, повтор и неправильный порядок

В Test Feed задайте scenario title. Ожидается title_required. Затем задайте duplicate: ожидается feed_duplicate. В обоих случаях успешного итогового предпросмотра не должно быть. Если получили JSON, проверьте, действительно ли Test Feed стоит перед Check Feed.

Теперь удалите Test Feed и напрямую соедините Read Demo Feed с Check Feed. В Sort News временно смените published_at с Descending на Ascending. Digest Preview должен остановиться с feed_order_mismatch. Верните Descending и убедитесь, что схема снова даёт результат из шага 8.

Шаг 12. Сохраните рабочий вариант

Проверьте, что осталось пять исходных узлов, URL снова указывает на учебный XML, Always Output Data включён только у RSS Read, Sort настроен по двум полям, а ошибок продолжения нет. Сохраните и выполните workflow ещё раз.

Повторный запуск вернёт те же три ID. RSS Read здесь читает файл целиком и не помнит, какие новости вы уже видели. Для реального ежедневного дайджеста понадобится отдельное хранилище обработанных ID и статусов. Добавлять расписание до такого контроля рано: оно повторит чтение, но само не решит задачу повторов.

Если результат отличается

Симптом Причина Что проверить
feed_empty Лента пуста или пришёл пустой объект Output RSS Read и Always Output Data
title_required Нет непустого заголовка title текущей записи
isoDate_required Парсер не получил пригодную дату pubDate исходного XML
feed_duplicate Повтор ID или ссылки в пакете guid и link всех записей
feed_order_mismatch Неверный порядок после Sort published_at Descending, id Ascending

Сетевая ошибка, ответ HTTP 503 или сломанный XML останавливаются ещё в Read Demo Feed. Проверяйте сообщение именно этого узла. Включение Ignore SSL Issues не исправит неверный адрес, HTML вместо RSS или ошибку сервера. On Error: Continue может превратить проблему чтения в обычный объект error — здесь этот режим не используется.

Что не делает этот прототип

Схема не проверяет факты новостей, не оценивает источник, не извлекает полную статью и не формирует связный текст дайджеста. Описание из RSS может быть коротким или устаревшим. Наличие даты и ссылки не делает сообщение достоверным. Перед публикацией нужны первоисточники и редакторская проверка.

Внешний RSS — недоверенный ввод. Не передавайте описание в AI как системную инструкцию, не исполняйте код из ленты и не вставляйте исходный HTML в страницу без безопасного вывода. Авторизация, Atom, нестандартные поля, большие ленты, тайм-ауты, расписание и хранение истории требуют отдельной проверки.

Разобрать XML в JSON с проверкой структуры

Извлечь поля из HTML без перемешивания карточек

Остановить workflow при неверных данных

Что проверено редакцией

16 октября 2026 года схема проверена на n8n 2.42.4 в отдельном Docker-экземпляре ручными запусками API. Все 29 тестов прошли: основной публичный XML, одна запись, обратный порядок, HTML в описании, равные даты, пустая и слишком длинная лента, отсутствие/пустота заголовка, ID, ссылки, даты и описания, HTTP и чужой домен в ссылке, повторы ID и ссылки, длинные тексты, сломанный XML, HTML вместо RSS, HTTP 503, неправильная сортировка, пустая лента без Always Output Data и четыре режима Test Feed. Основной тест использует точный скачиваемый workflow и опубликованный учебный XML. Остальные варианты — собственный локальный HTTP-источник и диагностический Code. Сверены порядок, поля, UTF-8, амперсанд, статус предпросмотра и отсутствие успешного результата при ошибках. Отдельно подтверждено: без Always Output Data пустая лента заканчивается без запуска проверочного Code. Настройки RSS Read 1.2 сверены с официальной документацией и кодом узла. Редакторские клики, Cloud, реальные новостные издания, Atom, авторизация, история между запусками, большие объёмы и полный аудит безопасности не тестировались. Учебный контейнер остановлен, существующие workflows не менялись. Обложка — редакционная AI-иллюстрация.

Частые вопросы

RSS Read сам напишет дайджест?

Нет. Он читает записи ленты. В примере получается проверенный JSON для редакторского предпросмотра, без AI-пересказа, проверки фактов и публикации.

Зачем Always Output Data у RSS Read?

При пустой ленте следующий узел иначе может не запуститься. С настройкой он получает пустой объект, который Check Feed отклоняет с feed_empty. Она не превращает сетевую ошибку в успешное чтение.

Почему нельзя открыть ссылки example.invalid?

Это намеренные заглушки вымышленной ленты. Рабочий адрес в примере — URL самого XML на ezgpt.ru. Workflow не переходит по ссылкам записей.

Повторный запуск не добавит те же новости?

В этом прототипе повторятся те же записи: постоянного хранилища истории нет. Для реальной сборки сохраняйте ID, источник и статус обработки отдельно; проверка дублей здесь работает только внутри одного пакета.

Можно сразу заменить URL своей лентой?

Сначала проверьте её поля и договор данных. В Code задан учебный домен example.invalid, обязательны guid, isoDate и contentSnippet. Для другого источника нужно осознанно настроить проверки и повторить тесты.

Дальше по теме

Похожие материалы