Агент анализа конкурентов

При подготовке урока первым конкурентом в список попал канал cofix, по имени похожий на известную сеть кофеен. Сценарий отработал без ошибок, а модель честно разобрала посты: «Sale ✅ … Write me». Под этим именем сидит не кофейня, а занятое имя, выставленное на продажу. Второй кандидат, coffeemania, вернул ноль постов. Сводка про несуществующего конкурента выглядит так же гладко, как про настоящего. Поэтому урок начинается с проверки глазами и только потом переходит к сценарию.

Чему научитесь в этом уроке:
• найти публичный канал конкурента и убедиться, что он настоящий и живой;
• собрать в n8n сценарий, который читает веб-ленту канала без ключей и паролей;
• получить от модели сводку тем, поводов и идей и отличить в ней проверяемые цифры от примерных.

Прогулка мимо витрин соседей

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

Телеграм-канал конкурента и есть такая витрина. У публичного канала есть веб-лента по адресу t.me/s/<имя канала>: обычная страница, которую открывает любой браузер без входа в Telegram. Сценарий n8n читает её тем же способом, что и браузер, простым запросом страницы. Ключи, пароли и бот для этого не нужны.

Что собирать можно, а что не стоит

Ниже правила здравого смысла. Юридической консультацией они не служат. Если сомневаетесь в конкретном случае, спросите юриста.

  • Только публичное. То, что видит любой прохожий: открытая веб-лента канала. Закрытые каналы, чаты по приглашению и разделы за входом не трогаем и не ищем к ним обходных путей.
  • Редко. Один запрос страницы на канал раз в неделю. Сотни запросов подряд похожи на атаку, и сайт может вас заблокировать.
  • Без людей. Собираем, что пишет компания: темы, акции, частоту. Имена, телефоны и комментарии покупателей в сводку не берём.
  • Для себя. Сводка нужна, чтобы придумать свои ходы. Чужие тексты и фото к себе не копируем.

Шаг ноль: открыть канал руками

Прежде чем вписывать имя канала в сценарий, откройте в браузере https://t.me/s/<имя> и ответьте на три вопроса:

  1. Это та компания? Название, описание, ссылки на сайт или адрес совпадают с конкурентом, которого вы знаете.
  2. Канал живой? Последний пост был недавно, посты идут хотя бы раз в неделю или две.
  3. Посты видны? Если страница пустая, сценарий тоже получит ноль постов. Так было с coffeemania.

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

А ВКонтакте?

Стену сообщества ВКонтакте читает метод wall.get. С ключом сообщества, который вы получали в уроке 3.6, он отвечает ошибкой 27: этот метод недоступен с ключом сообщества. Для чужой стены нужен сервисный ключ приложения ВКонтакте, а его создаёт владелец аккаунта в настройках своего приложения. В прогоне курса сервисный ключ не создавали и чтение стен ВКонтакте не проверяли, поэтому в уроке работаем только с Telegram.

Как устроен сценарий

Схема сценария n8n «Стена конкурента» слева направо: запуск (вручную или по понедельникам в 9:00), узел Code «Каналы конкурентов» со списком имён, узел HTTP Request «Лента канала» с адресом t.me/s/имя, узел Code «Посты», узел Basic LLM Chain «Разбор конкурента», узел Data Table «Insert row» в таблицу «Журнал аналитики». Под узлом «Посты» подпись «цифры считает код», под узлом разбора подпись «темы и идеи пишет модель».
  1. Запуск. Пока учитесь, это Manual Trigger, кнопка ручного запуска. В прогоне потом его заменили на Schedule Trigger, запуск по расписанию, с правилом 0 9 * * 1: каждый понедельник в 9:00.
  2. Code «Каналы конкурентов». Узел Code выполняет короткий кусок кода, который вы вставляете целиком. Здесь он хранит список каналов.
  3. HTTP Request «Лента канала». Этот узел открывает страницу по адресу, как браузер. Метод GET, в поле адреса выражение {{ "https://t.me/s/" + $json.channel }}: оно приклеивает к началу адреса имя канала из прошлого узла, в настройках Response Format = Text (страницу забираем как текст) и On Error = Continue (если один канал не открылся, сценарий не падает).
  4. Code «Посты». Достаёт из страницы текст, дату и просмотры каждого поста и сам считает: сколько постов, за какой период, сколько в среднем в неделю.
  5. Basic LLM Chain «Разбор конкурента». Модель читает посты и пишет сводку.
  6. Data Table «Insert row». Записывает итог строкой в таблицу «Журнал аналитики». Эту часть вместе с расписанием подробно соберём в практикуме 4.7, для первого запуска она не нужна.

Список каналов в узле «Каналы конкурентов». Замените skuratovcoffee на имя канала своего конкурента, а комментарий в первой строке оставьте как напоминание:

// Каналы конкурентов. Публичные каналы: сначала открыть t.me/s/<имя> руками и убедиться, что канал настоящий
return ['skuratovcoffee'].map(c => ({ json: { channel: c } }));

По плану курса конкурентов три: допишите имена через запятую в квадратных скобках, например ['skuratovcoffee', 'имя2', 'имя3']. Честно скажу: в прогоне разбирали один канал. Код рассчитан на список, но запуск с тремя каналами мы не проверяли.

Узел «Посты»: скопируйте код целиком, менять в нём ничего не нужно.

// Посты: текст, дата, просмотры из веб-ленты канала
const ch = $('Каналы конкурентов').all();
const clean = s => s.replace(/<br\s*\/?>/g, '\n').replace(/<[^>]+>/g, '').replace(/&#(\d+);/g, (_, n) => String.fromCharCode(n)).replace(/&quot;/g, '"').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').trim();
return $input.all().map((it, i) => {
  const h = String(it.json.data || '');
  const blocks = h.split('tgme_widget_message_wrap').slice(1);
  const posts = blocks.map(b => {
    const t = b.match(/tgme_widget_message_text[^>]*>([\s\S]*?)<\/div>/);
    const d = b.match(/datetime="([^"]+)"/);
    const v = b.match(/tgme_widget_message_views">([^<]+)</);
    return { date: d ? d[1].slice(0, 10) : '', views: v ? v[1] : '', text: t ? clean(t[1]) : '' };
  }).filter(p => p.text);
  const days = posts.length > 1 ? (new Date(posts[posts.length - 1].date) - new Date(posts[0].date)) / 864e5 : 0;
  return { json: { channel: ch[i].json.channel, count: posts.length, from: posts[0]?.date, to: posts[posts.length - 1]?.date,
    perWeek: days ? +(posts.length / days * 7).toFixed(1) : posts.length, posts } };
});

Что просим у модели

Системное сообщение узла «Разбор конкурента». Замените описание «Зерна» на свой бизнес:

Ты маркетолог маленькой кофейни «Зерно» в Твери (одна точка, своя обжарка не ведётся). Разбери канал конкурента по постам ниже.
Формат ответа — простой текст без звёздочек и решёток:
1. О чём пишут: 3–5 тем, у каждой — сколько постов и одна короткая цитата из поста в кавычках с датой.
2. Какие предложения и поводы: акции, новинки, события — только то, что есть в постах, с датой.
3. Частота и формат: возьми цифры из шапки, не пересчитывай.
4. Три идеи для «Зерна», которые реально сделать одной кофейне за неделю. Не предлагай того, что требует сети кофеен или своей обжарки.
Если чего-то в постах нет — так и пиши «в постах не найдено». Не придумывай цифры и факты.

В поле сообщения пользователя вставьте выражение. Оно собирает шапку с цифрами из кода и сами посты, каждый обрезан до 600 знаков:

{{ "Канал: @" + $json.channel + "\nПериод: " + $json.from + " — " + $json.to + ", постов: " + $json.count + ", в среднем в неделю: " + $json.perWeek + "\n\nПосты (дата | просмотры | текст):\n" + $json.posts.map(p => p.date + " | " + p.views + " | " + p.text.slice(0, 600)).join("\n---\n") }}

В третьем пункте системного сообщения частоту модель берёт из шапки и не считает сама. Считать посты по датам модели даются плохо, а код делает это без ошибок. В четвёртом пункте ограничение «одна кофейня, без своей обжарки» отсекает советы, которые подходят только сети.

Что вышло в прогоне и чему верить

Запуск 7 октября по каналу skuratovcoffee прошёл успешно. Код насчитал 17 постов с 10 сентября по 5 октября, в среднем 4,8 в неделю. Модель выдала темы с числом постов и цитатами, поводы с датами и три идеи для одной кофейни, без звёздочек и решёток.

Дальше мы проверили ответ кодом. Все 6 цитат из шести нашлись в постах дословно, значит, цитаты модель не придумала. Числа постов по темам модель посчитала сама, и проверить их нечем: границы темы нечёткие, и один пост можно отнести к двум темам. Поэтому в сводке три уровня доверия:

  • Точно: число постов, период и частота в неделю. Их считает код.
  • Проверяемо: цитаты с датами. Любую можно найти поиском в веб-ленте канала.
  • Примерно: сколько постов по каждой теме и идеи. Это мнение модели, читайте его как «в основном пишут про это».
Цитату в отчёт начальнику проверьте сами. Если сводка идёт дальше вас, откройте веб-ленту и найдите поиском браузера (Ctrl+F) одну-две цитаты. В прогоне все нашлись, но это один запуск на одном канале.

Раз в неделю, без вашего участия

Витрины соседей меняются медленно, поэтому смотреть чаще раза в неделю нет смысла. В прогоне сценарий запускается по понедельникам в 9:00, а итог ложится строкой в таблицу «Журнал аналитики»: в колонку summary уходит начало сводки, в колонку check строка вида «постов: 17, в неделю: 4.8». Через месяц в журнале видно, как менялась активность конкурента. Как включить расписание и завести журнал, разберём в практикуме 4.7.

Если не получилось

  • Постов ноль. Откройте t.me/s/<имя> в браузере. Если и там пусто, у канала нет публичной веб-ленты или имя неверное, возьмите другой канал.
  • Сводка про что-то странное: продажа, реклама, чужая тема. Имя канала занято не тем, кем вы думали. Найдите настоящий канал через сайт конкурента.
  • Узел «Посты» падает с ошибкой про имя узла. Код обращается к узлу по имени «Каналы конкурентов». Имя на холсте должно совпадать буква в букву.
  • В ответе модели английские слова. В прогоне модель вставила «Quote:» перед цитатой. Допишите в системное сообщение строку «Пиши только по-русски»; в прогоне эту правку не проверяли.
  • Частота в ответе не совпадает с шапкой. Верьте шапке, её считал код. Проверьте, что в системном сообщении есть пункт «возьми цифры из шапки, не пересчитывай».

Контрольный вопрос. Вы вписали в сценарий имя канала, похожее на название конкурента. Сценарий отработал без ошибок, сводка выглядит связно. Что нужно было сделать до запуска?

АПолучить у Telegram ключ для чтения каналов
БОткрыть веб-ленту канала в браузере и убедиться, что это та компания и канал живой
ВПоставить запуск по расписанию
ГУвеличить обрезку постов с 600 знаков

Подсказка: Вспомните, кто оказался под красивым именем в прогоне и почему сценарий этого не заметил.

На курсе задания проверяются автоматически. Подобрать курс

Контрольный вопрос. Какие цифры в сводке по конкуренту можно считать точными? Выберите все подходящие.

Выберите все верные варианты.

АСколько постов посвящено каждой теме
БОбщее число постов за период
ВСредняя частота постов в неделю
ГНасколько идеи подходят вашей кофейне

Подсказка: Какие числа посчитал код, а какие написала модель от себя?

На курсе задания проверяются автоматически. Подобрать курс

Контрольный вопрос. Вы хотите читать стену сообщества конкурента ВКонтакте методом wall.get с ключом своего сообщества. Что произойдёт, по опыту прогона?

АМетод вернёт посты без ограничений
БМетод вернёт ошибку 27: нужен сервисный ключ приложения
ВМетод вернёт только посты за последнюю неделю
ГМетод попросит войти в аккаунт конкурента

Подсказка: Ключ сообщества даёт права на своё сообщество. Хватит ли его для чужой стены?

На курсе задания проверяются автоматически. Подобрать курс

Задание. МИССИЯ «Прогулка мимо витрин». Найдите публичный Telegram-канал хотя бы одного конкурента (лучше трёх), откройте веб-ленту t.me/s/ в браузере и убедитесь, что канал настоящий и живой. Соберите сценарий из урока с ручным запуском и запустите его. Приложите: (1) имена каналов и по одной фразе, как вы убедились, что это тот конкурент; (2) цифры из узла «Посты»: число постов, период, частота в неделю; (3) ответ модели целиком; (4) две цитаты из ответа и пометку, нашли ли вы их в веб-ленте дословно; (5) одну идею из сводки, которую вы готовы сделать на этой неделе, или объяснение, почему ни одна не подходит. Принято, если: канал публичный и проверен руками до запуска; цифры взяты из узла «Посты», а не из ответа модели; обе цитаты сверены с веб-лентой, а ненайденная цитата честно отмечена; в сводке и приложениях нет имён и телефонов покупателей; данные собраны одним запуском, без массовых запросов.

Подсказка: Если ваши конкуренты не ведут Telegram, возьмите заметную компанию из вашей отрасли в другом городе: важно пройти весь путь от проверки канала до сверки цитат.

✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.

На курсе задания проверяются автоматически. Подобрать курс

Что дальше

Конкурентов вы теперь видите со стороны. В следующем уроке посмотрим на себя глазами гостей: модель разберёт 50 учебных отзывов о «Зерне».

Итог:
• веб-лента публичного канала t.me/s/<имя> читается обычным запросом страницы, без ключей;
• канал сначала проверяют руками: красивое имя может оказаться пустым или выставленным на продажу;
• число постов и частоту считает код, цитаты проверяются поиском, а темы и идеи от модели читаются как примерные.

← Назад  ·  ↑ В начало урока  ·  ⌂ В начало курса  ·  Вперёд →

Школа Виктора Комлева