Repost Vacancies
Это небольшое веб-приложение, которое, будучи размещённым на вашем хостинге или localhost, сможет через заданный интервал времени подключаться к общероссийской базе открытых данных Роструда с целью забрать новые вакансии для интересующего вас города, района или даже целого региона и опубликовать их в виде текстовых постов на вашем канале в мессенджере Telegram и/или Max.
Вообще говоря, приложение поначалу служило не более чем моим экспериментом по работе с открытыми данными. Оно создано в ноябре 2025 года на основе крошечного фреймворка Mimimi версии 7.3. Приложение представляло собой MVP (minimum viable product, то есть минимально жизнеспособный продукт) мультиканального парсера вакансий.
Однако позже приложение оказалось востребованным у определённого круга людей. Они могли мало понимать тонкости установки ПО подобного типа, поэтому я решил сделать ещё и переносную (portable) версию, выложив в общий доступ. Кому интересно, отличия этой версии от оригинальной перечислю в самом конце README.
Демо сайт
Имеется несколько живых примеров, как это приложение выглядит во время работы. Для данной цели, во-первых, был создан демонстрационный сайт с развёрнутым на нём приложением.
-
А это скриншот главной страницы того сайта.

Демо каналы
Во-вторых, впридачу к демо сайту были созданы несколько демонстрационных Telegram-каналов произвольных городов, чтобы показать, как результат парсинга вакансий выглядит в мессенджере. Ну и заодно убедиться, что MVP действительно выдерживает мультиканальную работу на протяжении многих месяцев и безошибочно парсит городские вакансии в заданные каналы.
-
А это скриншот того результата. Для примера взят Telegram-канал города Свердловск.

Вот полный список всех демо каналов. Они сохранены в рабочем состоянии по соображению, что на некоторые из них неожиданно стали подписываться безработные, и мне как-то не хотелось лишать людей этого способа искать работу:
- Алмазная
- Алчевск
- Антрацит
- Брянка
- Ирмино
- Кировск
- Краснодон
- Красный Луч
- Лисичанск
- Луганск
- Лутугино
- Новодружеск
- Первомайск
- Перевальск
- Ровеньки
- Рубежное
- Сватово
- Свердловск
- Северодонецк
- Стаханов
Создание демо каналов проходило по следующей схеме:
- Добавляю в свой Telegram-аккаунт новый канал.
- Пишу название канала, описание.
- Загружаю аватарку.
- Устанавливаю автоудаление постов через 30 дней (ниже объясню почему).
- Перевожу канал в публичный и даю подходящий никнейм.
- Ставлю запрет копирования из канала (ведь демо как никак).
- Добавляю своего бота в администраторы с единственным правом: публиковать сообщения.
При достижении лимита каналов на аккаунте использую следующий аккаунт. Конечно, большое количество городов мониторить частному лицу в принципе не потребуется, да и неудобно оперировать несколькими аккаунтами, но мне как разработчику хотелось знать, что приложение держит нагрузку.
Установка
Как я уже говорил выше, здесь в репозитории представлена переносная версия приложения, она вовсе не требует установки. Достаточно разместить содержимое папки repost-vacancies-v1 этого репозитория в некоторой папке вашего хостинга, например в корневой, и открыть в браузере URL той папки.
Технические требования
Приложение написано с использованием стека технологий PHP + SQLite + HTML + CSS + JavaScript, поэтому для его работы понадобится следующая конфигурация программного обеспечения:
- веб-сервер Apache 2.x;
- PHP версии 7.3 или выше;
- в конфигурации PHP включено расширение SQLite3.
В настоящее время такая конфигурация доступна на большинстве хостингов, в том числе российских. Если же вы предпочитаете запускать приложение локально, вот пример одной из возможных конфигураций. Скажем, на основе сборки XAMPP for Windows:
- Скачать сборку с официального сайта XAMPP.
- Установить на компьютер (предположим, вы захотели установить в папку
C:\WebServer). -
Раскомментировать в файле
C:\WebServer\php\php.iniследующую строку:;extension=sqlite3Подсказка: раскомментировать - значит убрать символ
;в начале строки.
Первичная настройка
Сразу после размещения приложения на хостинге следует провести его первичную настройку. Для этой цели приложение имеет бекенд с двумя дефолтными паролями разного назначения:
demoдля редактора сайта (его права ограничены при включенном режиме “демо”);testдля супервизора, обладающего неограниченными правами.
Важно: При первом запуске приложения рекомендуется немедленно авторизоваться с каждым паролём и сменить на безопасный. На следующих 5 скриншотах показано, как выглядит этот процесс.
Шаг 1. Переход на страницу авторизации.
Шаг 2. Авторизация с дефолтным паролём.
Шаг 3. Переход на страницу смены пароля.
Шаг 4. Указание нового пароля.
Шаг 5. Переход на страницу настроек сайта.
На странице настроек вам позволено менять следующие параметры:
-
В каком часу просыпается сканер. По умолчанию установлено на 8:00 утра, чтобы вакансии не сыпались подписчикам ночью и в ранние утренние часы.
-
В каком часу засыпает. По умолчанию установлено на 20:00, чтобы вакансии переставали сыпаться в часы вечернего отдыха и ночью.
-
Пауза между сканированиями в секундах. Её значение по умолчанию 300 секунд, это 5 минут, чего вполне достаточно для обслуживания пары десятков каналов с невысоким кадровым спросом. В случае обслуживания крупных городов спрос может быть выше, следовательно имеет смысл уменьшить паузу. Она влияет на максимальное число вакансий, публикуемых в одном канале в течение рабочих часов парсера. Например, при 5 минутах паузы и расписании с 8 утра до 8 вечера выходит не более 144 вакансий в сутки, то есть 60 минут в часе * (20:00 - 08:00) часов работы / 5 минут паузы.
-
Включен ли сканер вакансий. Значение 0 означает нет, 1 - да. То есть эта настройка может быть использована для временного отключения приложения без его удаления с хостинга.
-
Включен ли “демо” режим сайта. Эта настройка создана только для демонстрационного сайта. Её действие заключается в ограничении редактору сайта возможности сохранить произведённые им изменения. На вашем же хостинге эту настройку следует поставить равной 0. Значение 0 означает нет, 1 - да.
-
Токен бота, отправляющего вакансии в мессенжер Max. Это тот токен, что будет выдан вам на платформе Max для партнёров, когда создадите там профиль организации, ИП или самозанятого, а затем верифицируете профиль, создадите в нём бота и дождётесь его успешной модерации.
-
Токен бота, отправляющего вакансии в Telegram. Это тот токен, что будет выдан вам в Telegram, когда создадите нового бота через службу @BotFather.
Вот скриншот как установить токен. Предположим, был выдан токен 1234567890:ABCDEFGHijklmnopQRSTUVWXyz123456789.

Настройка парсинга
Шаг 1
Прежде всего вам следует создать бота в Telegram и/или Max, если ещё не создавали ранее. Бот будет использоваться для отправки спарсенных вакансий в Telegram и/или Max. Его токен следует сохранить в настройке, упоминавшейся выше на скриншоте.
Шаг 2
Далее следует создать публичный канал в Telegram и/или Max для вакансий интересующего вас города и добавить того бота в администраторы канала с правом публикации сообщений.
При организации мультиканальной работы следует учесть естетственные ограничения платформы Telegram: от имени простого аккаунта можно создать не более 10 публичных каналов, от имени Premium-аккаунта - не более 20 каналов.
Следует также учесть ограничения платформы Max: от имени аккаунта организации или ИП можно создать не более 10 публичных каналов, от имени аккаунта самозанятого - всего 1 канал.
Шаг 3
Затем надо создать задание парсинга для интересующего города, указав там его идентификатор. Примеры заполнения полей заданий можно посмотреть в живой демонстрации сайта, упоминавшейся выше в самом начале README.
Или вы можете с помощью кнопки Копия, отмеченной на следующих 2 скриншотах, использовать демонстрационное задание Кукуево как основу вашего будущего задания, указав в копии правильное имя города, правильное имя канала и заменив NNNNNNNNNNNNN на правильный идентификатор города.
Шаг 3.1. Переход на страницу заданий.
Шаг 3.2. Копирование задания как нового.
В форме редактора задания есть 4 типа полей, которые вы обязаны заполнить. На следующем скриншоте, изображающем момент сразу после нажатия кнопки Копия, те поля отмечены цветными прямоугольниками. Их цвет обозначает следующее:
- Зелёный это идентификатор интересующего вас города, района или региона. Ниже объясню, откуда его брать.
- Синий это имя города.
- Красный это выключатель активности задания (0 - выключено, 1 - включено, то есть разрешено к выполнению).
-
Коричневый это никнеймы каналов того города в соответствующих мессенджерах. Никнеймы следует писать без лидирующего символа
@.
Вид формы редактора задания.

Давайте теперь предположим, вы решили ввести сейчас задание для какого-нибудь города, ну например Курск. Посмотрим теперь на изменившийся скриншот с той же раскраской:
Вид отредактированной формы с данными для города Курск.
Поле Через сколько дней удалить спарсенные данные по умолчанию равно 30 дням, так как статистика платформы “Работа России” показывает, что медианный срок закрытия вакансий на платформе равен примерно 31 дню, а значит и у себя на сайте не имеет смысла хранить их дольше. Именно по той же причине я ставил автоудаление постов в демо каналах равным 30 дням.
Поле URL источника в системе открытых данных необязательно к заполнению, так как служит только возможности администратору мгновенно сравнить, правильно ли спарсились вакансии данного города. Для подобной возможности в карточку каждого задания встроена кнопка Источник данных, уводящая вас на соответствующе настроенный поисковый виджет платформы “Работа России”.
Откуда брать ИД города?
Хотя это приложение получает все данные через публичное API платформы “Работа России”, в том интерфейсе всё же отсутствует простой метод, который позволил бы внешнему приложению в автоматическом режиме сопоставить действующие идентификаторы с названиями городов, существующих в базе данных Роструда.
Поэтому при создании каждого задания приходится один раз вручную воспользоваться поисковым виджетом плафтормы, чтобы среди его GET-параметров увидеть идентификатор интересующего города. Для этого надо сначала выбрать в виджете регион, а потом уже город региона. Данный процесс показан на следующем скриншоте на примере города Курск.
Виджет поиска на платформе “Работа России”, где выбран город Курск.

Непосредственно парсинг
Когда вы закончили создание заданий, можно запускать сам парсинг. Для этого следует перейти на список заданий и нажать внизу кнопку Парсить, что показано на следующем скриншоте.
Переход на страницу парсинга.
Такой вариант парсинга использует симуляцию системного расписания (CRON-а) с помощью языка JavaScript, а значит будет действовать лишь пока вы держите страницу парсинга открытой.
Более эффективным вариантом является настройка физического CRON-а на вашем хостинге. Для этого надо скопировать URL, куда ведёт кнопка Парсить, и использовать его при создании CRON-задания. Если вы не айтишник и вообще не поняли, о чём сейчас речь, прочтите о кроне в Википедии или лучше попросите вашего сисадмина выполнить это действие.
Просмотр вакансий
Ясно, что основным дисплеем для просмотра вакансий будут являться ленты Telegram- и/или Max-каналов. Тем не менее, вы можете увидеть те же вакансии и на самом сайте приложения. Для этого надо перейти на Все или же только на вакансии конкретного города, как показано на следующем скриншоте.
Переход на страницу просмотра вакансий прямо на сайте.
Недостатки
Так как MVP приложения разрабатывался на скорую руку, в нём неизбежно появились несколько недочётов. Планируется устранить их поштучно в следующих версиях, если будет на то спрос. Вот эти недостатки:
-
Отсутствует поддержка мессенджера Max. То есть вы можете заполнить в настройках токен вашего Max-бота, указать в заданиях никнеймы ваших Max-каналов, но вакансии отправляться туда всё равно не будут.
-
Отсутствует проксирование запросов к мессенджеру Telegram. Из-за этого работа парсера бесполезна, если приложение развёрнуто на российском хостинге, так как оборудованию на стороне провайдера предписано блокировать подобные запросы.
-
Двойное преобразование HTML-сущностей, возникающее вследствие того, что некоторые сотрудники Центров занятости, перепечатывающие вакансии в базу Роструда, копипастят их текст из источника, уже преобразовавшего сущности. И тогда в тексте вакансии в Telegram-канале видны фрагменты наподобие
",—и другие. -
Порядок листания вакансий на сайте - от старых к новым, что очень неудобно, если хочется не выходя с сайта быстро проверить что появилось нового.
Предполагаю, найдутся желающие запилить собственную доработку приложения, а не ждать, пока это сделаю я. И тогда, наверное, ради лучшего понимания его устройства следует рассказать вам немного как об отличиях версий, так и о процессе создания оригинальной версии.
Отличия переносной версии
Я собирал её из оригинальной версии приложения, присутствующего под видом демо repost.vacancies в составе установочного пакета Mimimi Framework. Для портирования я взял пакет версии 7.4.
Вот изменения в файловой структуре пакета, выполненные мной в первую очередь. Они имитируют установку приложения, как если бы вы запустили её классическим образом:
- Удалил папку
mimimi.install- здесь был установщик фреймворка, работу которого я имитировал. - Из папки
mimimi.modulesудалил все базовые модули фреймворка, кромеSqliteиTelegram. - Удалил папки всех демо приложений, кроме интересовавшего меня
repost.vacancies. - Папку
repost.vacanciesпереименовал вmimimi.app.
Затем я сделал пару удалений от себя, чисто с целью ещё большей оптимизации:
- Удалил папку
media- здесь была папка демонстрационных медиафайлов. - Удалил неиспользуемые файлы и папки в ядре фреймворка
mimimi.core.
И наконец, выполнил несколько изменений в исходном коде приложения, опять же с целью оптимизации:
- Длинные многострочные комментарии во всех файлах заменил коротким однострочным пояснением что делает метод под ним.
- В файлах ниже главного модуля приложения удалил повторные подключения тех же файлов ядра, которые уже и так были подключены в главном модуле.
Что прочесть дополнительно
Наверняка вам будет полезным прочесть в приложении весь раздел Вопросы-Ответы. Он освещает общие вопросы про работу приложения.
Если же вы интересуетесь ещё и вопросом доработки, тогда непременно следует прочесть пошаговую историю создания приложения. Там расписано, зачем создавался каждый файл. Ищите эту историю по ссылке, изображённой на следующем скриншоте.

А на этой ноте я завершаю README, и напоследок хочу лишь заметить, что если у вас есть идеи по данному приложению, предложения, да и просто благодарности - я всегда с радостью их выслушаю.