Я написал ИИ-парсер, который рерайтит новости и публикует их в моём блоге
КодингУ меня есть сайт vesnins.ru. Ему много лет, он про фотографию, и в первую очередь про плёнку.
Часть контента там — новости: Kodak выпустил плёнку, Lomography запустил камеру, лаборатория закрылась. Я находил такие новости на зарубежных блогах, пересказывал по-русски и публиковал.
Это отнимает уйму времени. Я автоматизировал это.
Как это должно было работать
Скрипт раз в сутки читает RSS-ленты плёночных блогов. Нейросеть решает, что из этого новость, а что личный опыт или обзор. Потом пишет заметку на русском в моём стиле. Скрипт кладёт её в WordPress.
Перед началом я написал план проекта — партитуру, по которой работал.
ИИ создаёт черновики. Публикую я сам.
Нейросеть иногда путает чувствительность плёнки, цену или название. На сайте с многолетней репутацией такая ошибка видна сразу. Утром я открываю черновики, правлю пару фраз и жму «Опубликовать». Это сильно облегчает работу.
Ещё одно решение того дня: блоги — это детектор событий, а не источник текста. Заметку робот пишет по первоисточнику — пресс-релизу производителя или странице на Kickstarter. И всегда ставит ссылку.
Стена первая: я в России
Сайт живёт на российском хостинге Beget. Логично было поселить скрипт там же.
Первый же запрос к нейросети Google Gemini вернул ошибку: регион не поддерживается. Google закрыл Gemini для российских IP.
Попробовали OpenRouter — сервис-посредник к разным нейросетям. Его заблокировал уже сам хостинг.
Пришлось перенести скрипт на мой Mac. WordPress остался на Beget: скрипт стучится в него снаружи, через API.
Стена вторая: модели, которой больше нет
ИИ-редактор работает на gemini-3.5-flash.
У неё нашлась своя ловушка. Перед ответом модель «думает», и это нельзя отключить. Думание тратит тот же лимит токенов, что и ответ. Если лимит маленький, модель всё потратит на мысли и вернёт пустоту. При этом сервер ответит «всё хорошо».
Починил так: скрипт сам добавляет запас токенов. Если ответ всё равно пустой или обрезан, увеличивает запас и спрашивает заново.
Классификатор, который ничего не видел
Когда нейросеть наконец ответила, проверил классификатор — модуль, который отделяет новости от остального.
Оказалось, что в его запросе к модели не было самой новости. Ни заголовка, ни источника. Только инструкция: «реши, новость ли это». Модель отвечала наугад.
Со стороны это выглядело как работающий код. Он запускался, возвращал ответы и ничего не ронял.
Обнаружил и другую проблему. Анонс полукадровой камеры Lomography пришёл из двух источников. Нейросеть дала событию два разных ключа: те же слова, но в другом порядке. Робот решил, что это две новости. Научили его сравнивать ключи нечётко.
Переезд на сервер
Через несколько дней я понял, что мне не нравится. Скрипт живёт на ноутбуке и запускается руками. Это не автоматизация, а лабораторный стенд.
У меня был VPS. Поэтому парсер переехал налегке: без Docker и без отдельной базы данных. Только Python, файл SQLite и запуск по расписанию раз в сутки ночью.
Нейросеть, которая пишет за меня
Дальше — модуль рерайта. Скормил ей три моих старых заметки как образец стиля.
Модель неплохо меня пародирует. Но начала галлюцинировать — дописывать в конце «мнение автора». От моего имени. Мнение, которого у меня не было.
Я ввёл правило: модель вообще не знает о финале заметки. Место под мой комментарий и ссылку на источник добавляет код. Если модель всё же дописала финал сама, ответ идёт в брак.
Картинки скрипт ставит не ссылкой, а заливает в медиатеку сайта: источник может удалить файл, и пост сломается.
И это работает?
Следующий шаг: Telegram-бот, который присылает уведомления о новых черновиках.
Настроил расписание через cron — ночной запуск в 3:00 по Москве с защитой от наложения прогонов. Завёл лог. Завёл Git, чтобы сохранялась каждая версия кода.
Новая проблема: а где посты?
ИИ отклонял 95% записей. Слишком строгий получился фильтр.
Причин нашлось три.
- Классификатор судил по одному заголовку. Полный текст скачивался позже, уже после решения.
- Текст, который приходил в RSS-ленте, скрипт получал и выбрасывал.
- Ошибки записывались в базу, но не в лог. 9 августа рерайт упал, и в логе не осталось ни строчки. Со стороны это выглядело как «новостей сегодня не было».
Из-за этого робот отклонил, например, анонс плёнки Lomochrome Color '92 — ровно то, ради чего он создан.
Исправили все три. Классификатор теперь видит текст из ленты. Для PetaPixel, где плёнки мало, а цифры много, сделали бесплатный предфильтр по словарю: около 150 терминов вроде Portra, darkroom, Coolscan. Он отсекает около 95% лишнего ещё до нейросети. Если текста мало, черновик всё равно создаётся, но с пометкой «[МАЛО ТЕКСТА]», а модель получает запрет додумывать.
Блог 35mmc убрали: 30 записей, ни одной публикации.
Полуавтоматический режим
Каждый черновик я правлю руками. Текст по мелочи, мой вывод, иногда добавляю картинки. Перелинковка.
Как это работает сейчас
Ночью скрипт читает четыре ленты. Отсекает лишнее, находит дубли, скачивает первоисточник с картинками, пишет заметку и кладёт её черновиком в WordPress. Утром в Telegram приходит список.
Мне остаётся прочитать, вписать свой комментарий и опубликовать.