Настольная программа собирает промо-страницу из описания или по ссылке
Этот инструмент я сделал для собственной работы. Раньше каждая промо-страница была копией предыдущей: служебные теги, тексты, картинки и цвета правили вручную. Теперь программа собирает страницу из шаблона и описания или берёт содержимое готовой страницы по ссылке, а готовый архив сама выгружает на хостинг.
Каждая новая страница была копией предыдущей
Промо-страницу под новый товар или новый язык делали всегда одинаково: копировали папку предыдущей,
проходили вручную по всей разметке и переписывали всё, что относилось к старому проекту. Заголовок,
meta description,
весь блок og:*
(он отвечает за то, как ссылка выглядит в соцсетях), значок сайта, файл настроек с названием магазина
и ценами, вводные тексты, вопросы опроса, отзывы, блок предложения — и только потом изображения.
С изображениями ошибались чаще всего. У шаблона есть постоянные места: логотип на первом экране, логотип в шапке, значок сайта, фон страницы, фото товара, картинка для соцсетей. Файлы из источника приходят вперемешку с декоративными иконками, аватарами и значками, и на место логотипа то и дело попадало не то. К тому же за весом файлов никто не следил: исходник на несколько мегабайт уходил на живой сайт как есть.
Последний шаг тоже был ручным: собрать папку в архив, зайти в панель хостинга, создать группу, загрузить zip и разобраться с совпадением имён, если такая страница уже была. Один раз это терпимо. Но когда страниц несколько в неделю и у каждой есть варианты по языку и цветам, работа сводится к обслуживанию собственных копий.
Настольная программа разбирает источник и собирает страницу
Программа — обычное окно на tkinter, стандартной библиотеке Python для оконных интерфейсов. В ней есть вкладки: проект, содержимое, цвета, изображения, опрос, отзывы, публикация, журнал. Сервер и сборка не нужны: программа открывается двойным щелчком, файлы запуска для macOS и Windows лежат в репозитории. Работа идёт в одну сторону: источник разбирается, шаблон заполняется, результат отправляется на хостинг.
Папка с материалами и описанием или ссылка: встроенный загрузчик скачивает HTML и все файлы страницы
Заголовки, служебные теги, названия, цены, тексты, вопросы, отзывы, цвета из CSS
Логотип, значок сайта, фон и фото товара программа находит по разметке; поправить можно вручную в её окне
Шаблон и содержимое собираются в папку, картинки сжимаются, разметка проверяется автоматически
Архив собирается в памяти и уходит на хостинг через его API: группа, имя по шаблону, при совпадении имени — перезапись
Два семейства шаблонов в одном интерфейсе
В репозитории два шаблона:
template_1
на Bootstrap и
template_2
— статическая сборка на Astro со стилями в духе Tailwind. Разметка, имена файлов и набор мест
под содержимое у них разные. Поэтому при переключении шаблона программа перестраивает вкладки:
у каждого шаблона свои места под изображения, свой набор цветов и свои правила подстановки.
Для пользователя порядок работы остаётся тем же.
Страница по ссылке: встроенный загрузчик
Источником может быть папка на компьютере или адрес уже существующей страницы. Загрузчик написан на стандартной библиотеке Python и ведёт себя как аккуратный браузер:
- учитывает
<base href>, когда восстанавливает относительные пути - собирает файлы страницы из
img/link/script/source/srcsetи изurl(...)во встроенных стилях - проходит по CSS вглубь, включая
url()и@import, чтобы не потерять шрифты и фоны - скачивает файлы только с того же сайта; файлы с внешних CDN остаются ссылками
- перед разбором вырезает содержимое
<script>: иначе строки внутри встроенного JS принимаются заsrc=
Логотип, значок сайта и фон программа находит по разметке
Первая версия раскладывала картинки по местам, угадывая по имени и размеру файла, и подставляла
в шапку случайные картинки. Теперь главное — разметка: значок сайта (фавикон) берётся из
<link rel="icon">,
логотип — из шапки и из alt/class
со словами logo/brand, фон — из
background-image: url(...)
у body/html,
картинки отзывов — из своих блоков. Угадывание по имени и весу осталось только запасным
вариантом. Декоративные иконки, аватарки и значки внесены в список исключений и больше
не оказываются на месте логотипа. Всё, что программа не смогла определить, видно в интерфейсе
и правится вручную.
Цвета берутся с исходной страницы
Программа читает HTML вместе с подключёнными файлами CSS и достаёт цвета из переменных темы.
Если цвет задан несколько раз, берётся последнее значение, потому что тема должна перекрывать
базовые стили. Цвета из
hex,
rgb()
и oklch()
приводятся к одному виду. Серые и почти белые отбрасываются, а остальные распределяются по ролям:
кнопка, текст кнопки, шапка, фон страницы, карточка, акцент. Дальше цвета видны в интерфейсе
как обычные поля, и любой из них можно поправить.
Проект хранится в файле JSON
Всё о сборке сохраняется в файл проекта: выбранный шаблон, пути, всё содержимое, цвета, раскладка картинок по местам, вопросы, отзывы. Чтобы повторить страницу или сделать вариант, достаточно открыть проект и поправить пару полей. Файлы проектов лежат в репозитории рядом с кодом, поэтому у каждой сборки есть история версий.
Картинки сжимаются перед публикацией
Каждый файл, который попадает в шаблон, проходит через Pillow, библиотеку для работы с картинками. Она уменьшает картинку по большей стороне, сохраняет прозрачность у PNG и WebP и выбирает разумное качество. Если Pillow недоступен, файлы просто копируются, и сборка не прерывается. Вручную за такими мелочами на каждой странице не уследишь.
Перед публикацией программа проверяет разметку
У готовой страницы есть обязательные элементы, которые легко потерять при правке шаблона. Это скрытые метки, на место которых хостинг подставляет данные при показе страницы, и общий идентификатор события для аналитики в браузере и на сервере. Программа проверяет их перед выгрузкой: если чего-то нет, восстанавливает и пишет предупреждение в журнал. Правка шаблона не должна незаметно ломать учёт событий: когда статистика молча показывает нули, это замечают слишком поздно.
Публикация в одно действие, даже если имя уже занято
Готовая папка упаковывается в ZIP прямо в памяти (служебные файлы вроде
.DS_Store
отсеиваются), кодируется в base64 и отправляется на хостинг через его API. Существующие группы
подгружаются в выпадающий список, а имя страницы собирается по шаблону вида
{store} - {product} - {template} - {lang}.
Если хостинг отвечает ошибкой 422
«имя занято», работа не прерывается: программа находит существующую запись и спрашивает, перезаписать
ли её. Если согласиться, она отправляет запрос PUT
по найденному id. Ключ доступа хранится вне репозитория, в локальном файле настроек, который может
читать только владелец (права 600).
Правила оформления лежат рядом с кодом
В репозитории лежат три брифа. Первый описывает общие основы: шрифты, сетку, состояния элементов, мобильную версию и допустимый вес страницы. Ещё два написаны для каждого семейства шаблонов: в них разобран каждый CSS-селектор, перечислено, что убрать и что добавить, и есть список для проверки. Программа отвечает за структуру, брифы — за внешний вид. Без брифов программа просто быстрее тиражировала бы неудачную вёрстку.
Программа без сборки открывается двойным щелчком
Приложение на компьютере: без сервера и без отдельного шага сборки
Разбор исходной страницы: служебные теги, тексты, цены, вопросы, отзывы
Загрузка страницы по ссылке и обращения к API хостинга
Предпросмотр в интерфейсе и сжатие картинок перед публикацией
Упаковка результата в памяти и выгрузка архива через API
Все настройки сборки лежат в файле: страницу можно повторить или сделать вариант
Первое семейство шаблонов со своим набором мест под содержимое
Второе семейство: статическая сборка на Astro со стилями в духе Tailwind
Правила оформления: общие основы и бриф для каждого семейства
Файлы запуска для macOS и Windows: программа открывается двойным щелчком
Страница собирается из проекта
ручную правку разметки заменил один запуск программы
архив, группа, имя и совпадение имён программа берёт на себя
коммитов; правки приходили из реальных сборок
Типовые ошибки теперь ловятся до выгрузки
Забытый og:image,
значок сайта от прошлого проекта, логотип не на своём месте, картинка на несколько мегабайт, фон,
потерянный при переносе, — всё это раньше замечали глазами уже на живой странице. Теперь эти вещи
либо вынесены в интерфейс отдельными полями, либо проверяются автоматически перед выгрузкой.
История коммитов — список найденных ошибок
Инструмент доводился на реальных сборках, и почти каждый коммит исправлял конкретную ошибку. Логотип из-за анимации увеличивался на доли пикселя. Относительные пути ломались при переносе. Совпадение имён при повторной выгрузке раньше просто прерывало работу. Мелкие иконки программа принимала за логотип. Такие вещи заранее не предусмотришь, они обнаруживаются в работе. Поэтому инструмент под свой процесс имеет смысл дорабатывать на живых задачах.
Ограничения
Это внутренний инструмент. Интерфейс не покрыт автоматическими тестами. Качество разбора напрямую зависит от того, насколько аккуратно свёрстан источник. На нестандартной странице программа заполняет часть полей неверно. Поэтому всё, что она определила, можно отредактировать, а журнал показывает каждый шаг. Пользователь всегда видит, что именно подставлено и откуда.
Где ещё работает тот же подход
За кейсом стоит типовая задача: «шаблон и содержимое → готовая страница → публикация без ручных шагов». Схема почти без изменений подходит везде, где однотипные страницы делают вручную:
- → Страницы на нескольких языках и для нескольких брендов — одна сборка, разные проекты: язык, цвета, логотип, тексты
- → Посадочные страницы для каждого товара из выгрузки каталога — собираются партиями, без ручной вёрстки
- → Тиражирование сайтов сети или франшизы — общий шаблон, свои контакты, цвета и логотип на каждую точку
- → Перенос существующей страницы на новый шаблон — загрузчик скачивает исходную страницу, а разбор достаёт из неё содержимое и цвета
- → Подготовка вариантов для сравнительных тестов — те же тексты, другие цвета и раскладка картинок, публикация одной очередью
- → Тот же код без интерфейса — как шаг автоматической сборки (CI): на входе проект в JSON, на выходе опубликованная страница
- Загрузчик страницы: проход по CSS вглубь, файлы только с того же сайта, исходная структура папок
- Раскладка изображений по местам: сначала по разметке, потом по имени и весу, и всегда с возможностью поправить вручную
- Цвета из CSS-переменных: hex, rgb и oklch, тема перекрывает базовые стили, серые отсеиваются
- Проект в JSON: сборку можно повторить, хранить её версии и брать за основу для варианта
- Проверка обязательных меток в разметке перед публикацией: недостающие восстанавливаются, в журнал пишется предупреждение
- Публикация на хостинг или в CMS через API: архив в памяти, base64, перезапись при совпадении имени
Если каждая страница — копия предыдущей, её можно собирать программой
Свой инструмент оправдывает себя там, где однотипные страницы делают каждую неделю. Начинать стоит с одного шаблона, одного формата источника и одного места публикации. Остальное добавляется по ходу реальной работы. Делать такие программы самостоятельно можно научиться на уроках по вайбкодингу.
Похожие кейсы и готовые решения
Приложение для онлайн-школы напоминает об уроках и тренирует произношение
Приложение для iPhone на SwiftUI (iOS 17 и новее) напоминает о занятии за сутки, за час и за 10 минут…
Приложение для фитнес-студии ставится из браузера и обновляется без App Store
Веб-приложение (PWA) ставится на экран «Домой» iPhone прямо из Safari, работает без сети и напоминает о…
Android-приложение: встроенный браузер, разбор APK и подготовка релиза
Локальные экраны на Kotlin, WebView с файлами и разрешениями, восстановление состояния. Частичный разбор…