Перейти к содержимому
Content 365
Назад

Новостной конвейер на PowerShell: пять материалов в день за три минуты, человек только на согласовании

Обложка статьи «Новостной конвейер на PowerShell: пять материалов в день за три минуты, человек только на согласовании»

Автоматизация создания контента обычно выглядит так: «нейросеть пишет статью, скрипт её публикует». Автор кейса на Хабре «Новостной конвейер на PowerShell: три минуты от ленты источников до готовой страницы» описывает другую схему. Его конвейер выпускает пять материалов в день о мире LLM, и в нём модель вызывается четыре раза под узкие задачи. Человек остаётся в одной точке: на воротах согласования, где у него десять минут на решение.

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

Отдельно о сути эксперимента. Автор проверял не трафик, а инженерную гипотезу: может ли один человек с PowerShell и недорогой моделью держать ежедневный ритм публикаций без редакции.

Задача: новостной сайт на нейросети без редакции и бюджета

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

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

Инфраструктура минимальная. Сайт статический, из HTML-файлов, лежит на обычном хостинге с FTP, без серверной части и базы данных. Управляет всем PowerShell 5.1 на машине автора: 47 скриптов, около 9,7 тысячи строк.

Результат за две недели:

ПоказательЗначение
Карточек в журнале / опубликовано61 / 56
Вечерних сводок подряд7
Время прогона одного материалаоколо 3 минут
Токенов на материал2,5–4,5 тысячи
Адресов в карте сайта / в индексе Google на 23 октября76 / 54 (71 %)
Оповещений IndexNow45

Трафик, по словам автора, на старте почти нулевой, и он считает это ожидаемым: сайту две недели, а новостные запросы в поиске конкурентны. За это время конвейер не сорвал ни одного дня, а все аварии были техническими и лечились в тот же вечер.

Журнал вместо базы и гейт по файлу

От базы данных автор отказался легко: данные конвейера линейны. Есть карточка темы, её состояние и обогащения. Поэтому журнал — это файл JSONL, одна строка на материал. Каждый шаг читает строку, дописывает свои поля и сохраняет обратно. Ни один шаг не хранит состояние у себя.

В карточке лежат заголовок, адрес первоисточника, рубрика, дата, язык, лид, статус, номер темы, список источников, таблица фактов, вывод, блок «полезно», результат фактчека и FAQ. Постоянный адрес страницы вычисляется из данных: дата плюс первые восемь шестнадцатеричных знаков SHA-1 от адреса первоисточника. Получается короткое имя вроде 2026-10-22-2ea2fcfc.html, без транслита и без коллизий в пределах дня.

Ключевым приёмом автор называет то, что гейт публикации проверяет файл, а не флаг. Материал считается опубликованным, только когда на диске есть его HTML-страница. Из этого следует несколько вещей:

Как устроена автоматизация создания контента: цепочка за три минуты

Каждый шаг запускается отдельным процессом PowerShell. Запуск выходит дороже, зато падение одного шага не убивает прогон: конвейер записывает шаг в список упавших и идёт дальше, а материал дорабатывается при следующем запуске. Автор приводит секунды из лога прогона 22 октября:

ШагЧто делаетСекунды
сбор новостейопрос лент, отбор кандидатов29 (17 кандидатов)
поиск источниковдополнительные источники по сырому заголовку3
адаптациязаголовок 45–65 знаков, лид 200–450 знаков6
регистрация темыномер темы и сверка на дубли по всему журналу3
анкорыфакт в 8–14 слов на каждый источник17
фактытаблица фактов, «что это значит», «что полезно вам»17
проверка фактовсверка утверждений с текстом первоисточника14
автопочинкаисправление неудачных проверок до публикации15
картинкагенерация в локальной модели68
FAQчетыре вопроса-ответа для разметки6
сборкастраница, лента, карта сайта, RSS2

Прогон стартовал в 17:00:02, материал зафиксирован в 17:03:04. Дольше всего работает генерация картинки на локальной видеокарте, 68 секунд. LLM-шаги в сумме занимают 46 секунд.

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

Четыре узких вызова модели

Целиком статью модель не пишет. Каждый из четырёх вызовов решает узкую задачу и возвращает ответ в жёстком формате. По словам автора, так дешевле и стабильнее, а главное, каждую часть можно перепроверить отдельно.

ВызовЗадачаЛимит токеновНа замере
адаптациязаголовок и лид из англоязычного материала900около 950 токенов, 3–4 с
анкорыпо факту на каждый источник300177 токенов, 1,9 с
фактыфакты, вывод, «полезно» (300–500 слов)2 6001 054 токена, 5,7 с
FAQчетыре пары «вопрос-ответ»1 200286 токенов, 2,7 с

На материал уходит 2,5–4,5 тысячи токенов. Автор оценивает это в доли цента при текущих тарифах и делает вывод, что узкое место — качество контракта, а не деньги. Поэтому факты принимаются только в заданной структуре. Если в ответе нет обязательных полей, шаг переспрашивает модель: три попытки с паузой. Сам вызов — обычный HTTP-запрос из PowerShell, без SDK и внешних библиотек.

Модель вынесена в настройки

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

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

Ворота согласования: автоматический постинг новостей, но не без спроса

Публиковать «в интернет без спроса» автор не хотел даже в собственном проекте. Готовая карточка получает номер темы и попадает в hold-список, из которого страница на сервер не выгружается. Одновременно автору приходит письмо и событие в журнал Windows. Сторож ждёт решения десять минут. При «да» он снимает тему с холда, выгружает сайт, обновляет карту и оповещает поисковики. Если решения нет, тема ждёт следующего раза, а прогон продолжается.

Две детали оказались важнее, чем автор ожидал. Первая — дедлайн: без него «согласую потом» превращается в очередь из двадцати материалов и публикацию пачкой, а это ломает ежедневный ритм. Вторая — согласование держится на hold-списке и отдельном каталоге, а не на флаге в карточке. Что ждёт решения, видно по файлам, даже если почта не открыта.

Выгрузка и поисковики

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

После успешной выгрузки работают три канала оповещения. Карта сайта уходит через API Search Console. Отдельные адреса отправляются через Indexing API с паузой два дня на адрес, иначе квота сгорает на повторах. Для Яндекса и Bing используется IndexNow. Сбой любого канала деплой не ломает: уведомления копятся в очереди до следующего прогона. API Вебмастера Яндекса на момент статьи не работал у автора тринадцатый день, а сайт продолжал выходить.

Отдельный урок касается FTP-хостинга: листинг не показывает файлы, имя которых начинается с точки. Файл .htaccess с редиректами и заголовками безопасности существует и работает, но в листинге его не видно. Проверять скрытые файлы автор советует запросом самого файла. Иначе можно однажды выгрузить сайт «как есть» и потерять редиректы.

Пять поломок и что автор сделал бы иначе

Автор подчёркивает, что все пять случаев взяты из этой системы и уже исправлены.

  1. Рассуждающая модель съедает лимит. Модель deepseek-v4.1-flash на шлюзе B.AI возвращает блок рассуждений, и он считается внутри max_tokens. При лимите 70 токенов ответ пришёл пустым, с 287 знаками рассуждений. При 400 картина повторилась: 1090 знаков рассуждений и снова пустой ответ. Помог флаг reasoning_effort: 'none', после него ответ приходит за 2–6 секунд. Значение low не помогает. Совет автора: сначала проверить, входит ли блок рассуждений в лимит, и только потом поднимать max_tokens.
  2. Регистр в именах переменных. Для PowerShell $S и $s — одна переменная. В первый раз цикл затёр путь к папке скриптов. Во второй подключаемый резолвер модели объявил свою переменную с тем же именем, что у пути к кэшу сводки. Текст сводки записался в файл кэша модели, и ни одной ошибки при этом не возникло. Вывод автора: подключение через точку выполняет чужой код в вашей области видимости, поэтому имена в модулях стоит префиксовать.
  3. Скрипт без BOM читается как CP1251. При запуске по расписанию файл в UTF-8 без BOM читается в системной кодировке, и кириллица превращается в мусор вплоть до ошибки парсера. Интерактивный запуск того же файла работает. Автор дописывает BOM после каждой правки и называет забытый BOM причиной половины «мистических» падений по расписанию.
  4. Двоеточие после переменной. Строка вида "Итоги за $дата:" не компилируется: двоеточие читается как указание диска. Нужно писать ${дата}:. Ошибка прилетает в шаблонах сообщений, то есть в самом конце работы.
  5. Без картинки нет страницы. Если генератор картинки падал по таймауту локальной модели, материал молча выпадал из публикации. Квота дня израсходована, статья «принята», на сайте её нет. Лечение — строгий порядок шагов и блок восстановления: на старте прогона конвейер досоздаёт картинку и страницу для карточек с темой, но без страницы.

Иначе автор сделал бы три вещи. Сразу вынес бы модель в резолвер. С первого дня сделал бы шаги идемпотентными, с кэшем результата: на сводках повторный прогон за прошедшую дату переписывал уже опубликованный и проиндексированный текст. И не отдавал бы код 200 на адреса с index.html: через месяц поисковик насчитал тринадцать дублей страниц и прислал письмо о проблемах индексации.

Коротко

Что из этого следует

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

Условия у кейса узкие. Это новостной сайт о LLM, статический хостинг и две недели работы, а метрики относятся к индексации, а не к посещаемости. Сам автор пишет, что трафика пока почти нет. На практике это, скорее всего, значит, что кейс подтверждает выполнимость ритма, а не его отдачу.

У себя стоит проверить три вещи. Входит ли блок рассуждений вашей модели в лимит токенов. Что происходит с материалом, если упал один промежуточный шаг. И видно ли без открытия почты, что сейчас ждёт вашего решения.


Источник: Новостной конвейер на PowerShell: три минуты от ленты источников до готовой страницы


Поделиться статьёй:

Предыдущая статья
Автоматизация контент маркетинга с кнопкой «одобрить»: что обещает overads.io и как устроен подход
Следующая статья
Квалификация лидов в n8n: как ИИ-агент решает за аналитика и где это опасно