Инструкция, как поднять такой же под свою профессию за вечер
Летом я искала работу продактом. Как и все, подписалась на десяток телеграм-каналов с вакансиями и каждое утро их листала. Проблемы:
— каналов много, в день в них 50+ постов, из них мне подходят два-три;
— одна и та же вакансия висит в четырёх каналах, и каждый раз ты её перечитываешь, пока не вспомнишь, что уже видела;
— фильтров нет никаких: ни по грейду, ни по городу, ни по «удалёнке», ни по ML, только глазами;
— половина постов не вакансии, а курсы, разборы резюме и «ищу работу».
Платные агрегаторы существуют, но платить за то, чтобы читать бесплатные каналы, мне не хотелось. Хотелось одну страницу, где всё это лежит с фильтрами, без дублей, и обновляется само.
Вообщем накодила + навайбкодила. Работает вроде chernoyarova.github.io/tg_digest + один человечек написал в линке, что вот то и то еще добавьте, я подумала фигасе, юзают чтоли. Может стоит как-то адаптировать, чтоб люди у себя смогли поднять по-быстрому. Сделала YAML-файл под любую профессию, не только для продактов. Вообщем, с работой щас не просто, поэтому может кому будет полезно форкнуть.

Что получилось
Одна статичная страница, которую генерирует скрипт раз в день:
— Все каналы в одном месте. Скрипт читает папку в вашем Telegram: добавили канал в папку со следующего дня он в дайджесте. Списка каналов в конфиге нет.
— Без дублей. Вакансия, которую перепостили в четыре канала, показывается один раз, с пометкой «ещё в 3 каналах» и ссылками на все.
— Только вакансии. Курсы, вебинары, «ищу работу», реклама и митапы отсеиваются.
— Поля вытащены из текста: компания, грейд, город, удалёнка, зарплата (если указана), теги ML/AI для продактов, React / Vue / TypeScript для фронтенда.
— Фильтры и поиск: по периоду (24 часа / неделя / месяц / архив), грейду, локации (Москва, Питер, регионы, за рубежом, удалёнка), тегам, плюс поиск по тексту.
— Полный пост в один клик, со всеми ссылками из него, включая скрытые.
— Подборки разобраны. Если канал публикует «5 вакансий недели» одним постом, каждая становится отдельной карточкой.
Стоимость: ноль. GitHub Actions запускает скрипт раз в день, GitHub Pages отдаёт страницу, оба бесплатны для публичных репозиториев. Единственные ключи — от Telegram API, они тоже бесплатные.
Как это работает
Шесть шагов:
fetch_tg → parse → enrich → deduplicate → state → render
Telethon regex правила SequenceMatcher NEW/архив Jinja2
1. fetch_tg через Telethon читает все каналы из папки, забирает посты с прошлого запуска.
2. parse быстрый фильтр регуляркой: в посте вообще упоминается нужная роль?
3. enrich правила решают, вакансия ли это (есть ли «ищем», «требования», «откликнуться»; нет ли «курс», «вебинар», «ищу работу»), и вытаскивают поля: заголовок, компанию, грейд, город, зарплату, теги. Ничего не генерируется
4. deduplicate сравнивает тексты через difflib.SequenceMatcher, похожие на 90%+ склеивает.
5. state помечает новое, отправляет старое в архив, удаляет то, чему больше 90 дней.
6. render Jinja2 собирает одну страницу index.html с данными внутри. Фильтры и поиск работают в браузере на чистом JS, сервера нет.
Почему без нейросети
Первая версия использовала LLM для третьего шага: модель классифицировала пост и возвращала JSON с полями. Работало хорошо. А потом ключ API протух, скрипт падал с 401, и дайджест неделю не обновлялся, пока я не заметила. Плюс это единственная платная часть во всей схеме.
Я заменила модель правилами и регулярками. Стало чуть хуже: грейд теперь пустой у 38% карточек, потому что ставится только когда в посте прямо написан уровень; пара нерелевантных постов в день проскакивает. Зато ноль зависимостей, ноль денег, и точно известно, почему карточка выглядит так, а не иначе. Для личного инструмента это правильный размен. Если для вас нет — шаг enrich изолирован, туда можно вернуть любую модель.
Что требуется чтобы установить:
— открыть терминал и выполнить пять команд по инструкции;
— установить Python 3.11 (brew install python / установщик с python.org);
— завести аккаунт на GitHub и нажать несколько кнопок в настройках репозитория;
— для своей профессии — подправить регулярки. Если слово «регулярка» пугает: это выражения вида \bfrontend\b|фронтенд\w*, их за вас напишет любой ChatGPT или Claude по описанию «мне нужны паттерны для слов „тестировщик“ во всех падежах».
Программировать не нужно. Я не разработчик.
Инструкция
1. Форк и установка
Нажмите Fork на https://github.com/chernoyarova/tg_digest, потом:
bash
git clone https://github.com/<ваш-логин>/tg_digest.git
cd tg_digest
python3 -m venv .venv
source .venv/bin/activate
Windows:
.venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
2. Ключи Telegram
Зайдите на https://my.telegram.org → API development tools → создайте приложение (название любое). Скопируйте api_id и api_hash в файл .env:
TG_API_ID=12345678
TG_API_HASH=0123456789abcdef0123456789abcdef
Затем один раз залогиньтесь, чтобы получить сессию:
bash
python scripts/generate_session.py
Скрипт спросит номер телефона, код из Telegram и пароль двухфакторки, если есть. В ответ напечатает длинную строку, вставьте её в .env как TG_SESSION_B64. Это ваш логин в Telegram в зашифрованном виде, никому его не показывайте и не коммитьте (.env уже в .gitignore). Если не получится, в конце статьи есть ссылка на статью, может поможет
3. Папка с каналами
В Telegram создайте папку (Настройки → Папки) с названием vacancy и перетащите в неё каналы с вакансиями. Всё. Название папки можно поменять в config/sources.yml, ключ tg_folder_name.
4. Первый запуск
bash
python scripts/main.py
open index.html
Windows:
start index.html
Первый запуск заберёт посты за последние 30 дней, это минута-две. Откроется страница с вашими вакансиями. Посмотрите на карточки: если в них мусор, это момент подправить правила (см. раздел про профили), а не после публикации.
5. Публикация на GitHub Pages
Чтобы страница обновлялась сама, нужно отдать те же три ключа GitHub:
1. В репозитории: Settings → Secrets and variables → Actions → New repository secret. Заведите три секрета: TG_API_ID, TG_API_HASH, TG_SESSION_B64 — значения из вашего .env.
2. Actions → digest → Run workflow. Это первый прогон в облаке, он создаст ветку gh-pages с готовой страницей.
3. Settings → Pages → Source: ветка gh-pages, папка /.
Через минуту страница появится по адресу https://<ваш-логин>.github.io/tg_digest/. Дальше workflow запускается сам каждое утро.
Одна оговорка: GitHub запускает расписания с опозданием, иногда на несколько часов. У меня сборка стоит на 06:23 МСК, а реально проходит около десяти утра. Если нужно точнее, запускайте вручную кнопкой Run workflow.
6. Своя профессия
Скрипт ничего не знает про продактов или фронтендеров. Он задаёт каждому посту четыре вопроса, а ответы берёт из файла профиля — profiles/product.yml или profiles/frontend.yml. Чтобы сделать дайджест для своей профессии, надо ответить на те же вопросы про неё. Разберу на примере QA-инженера.
Вопрос 1. Как называют вашу роль?
Пост берётся в работу только если в нём встретилось одно из этих слов. Перечислите все написания, в которых вы видели вакансию: по-русски, по-английски, сленг.
yaml
roles:
patterns:
- '\bqa\b'
- '\bтестировщик\w*'
- '\btest automation\b'
Про запись: это регулярные выражения. \b значит «граница слова» (чтобы qa не находилось внутри aqua), \w* значит «и любое окончание» (тестировщик, тестировщика, тестировщику). Больше знать не нужно; если хотите добавить слово, попросите ChatGPT или Claude: «напиши регулярку для слова „автотестер“ во всех падежах».
Вопрос 2. Какие слова похожи на вашу роль, но не она?
Слово «тест» есть и в «A/B-тест» у продактов, и в «тестовое задание». По нему стоит взять пост на рассмотрение, но нельзя решать, что вакансия про QA. Такие слова идут в loose:
yaml
loose:
- '\bтест\w*'
Вопрос 3. Какие соседние роли надо выкидывать?
Это самый важный список. Пост про разработчика может упоминать QA в требованиях («умеете работать с тестировщиками»), и по первому вопросу он пройдёт. Поэтому после того, как скрипт определил заголовок карточки, он проверяет: если в заголовке названа роль из exclude и нет вашей, карточка выбрасывается.
yaml
exclude:
- 'разработчик|developer|аналитик|analyst'
- 'продакт|product manager|проджект|project manager'
Точность дайджеста берётся именно отсюда. После первого запуска пролистайте карточки и добавьте сюда всё, что проскочило.
Вопрос 4. Как узнать вашу вакансию внутри подборки?
Некоторые каналы публикуют по пять вакансий одним постом. Скрипт режет такой пост на отдельные карточки и по короткому заголовку каждой решает, ваша она или нет. Здесь достаточно одного-двух корней:
yaml
hint:
- 'qa|тест'
Необязательное: грейды и теги.
Слова «senior», «junior», «стажёр», «lead» скрипт знает сам. Если у вашей роли есть свои названия уровней, добавьте их:
yaml
grades_extra:
Head: 'head of qa|руководител\w+ отдела тестирования'
Lead: 'qa lead|лид тестирования'
Теги это то, по чему вы хотите фильтровать сверх грейда и города. Каждый тег появится чипом на карточке и тумблером «Только …» в фильтрах. У продактов это ML/AI, у фронтендеров React, Vue и TypeScript. Для QA логично завести «Автотесты»:
yaml
tags:
- key: automation # имя поля, латиницей
label: Автотесты # надпись на чипе и тумблере
pattern: 'автотест\w*|automation|selenium|playwright'
Заголовок страницы тоже берётся из профиля:
yaml
site:
title: QA jobs
tagline: from Telegram
Собранный целиком файл profiles/qa.yml выглядит так:
yaml
site:
title: QA jobs
tagline: from Telegram
roles:
patterns:
- '\bqa\b'
- '\bтестировщик\w*'
- '\btest automation\b'
loose:
- '\bтест\w*'
hint:
- 'qa|тест'
exclude:
- 'разработчик|developer|аналитик|analyst'
- 'продакт|product manager|проджект|project manager'
grades_extra:
Head: 'head of qa|руководител\w+ отдела тестирования'
Lead: 'qa lead|лид тестирования'
tags:
- key: automation
label: Автотесты
pattern: 'автотест\w*|automation|selenium|playwright'
Осталось в config/sources.yml написать profile: qa и запустить python scripts/main.py. Этот профиль я написала для примера и на реальных каналах не проверяла. Обычно хватает двух-трёх итераций «запустила, посмотрела карточки, дописала exclude«.
Ещё одна настройка, которая понадобится не всем. Если какой-то канал вставляет в каждый пост одну и ту же строку (навигацию по своим каналам, рекламу бота), она будет лезть в заголовки карточек. В config/sources.yml для этого есть ignore_lines — список регулярок, такие строки скрипт пропускает:
yaml
ignore_lines:
- '^Вакансии\s*│'
- 'первый ai ассистент'
Либо можно не упарываться, скачайте себе клод код, скиньте ссылкой ему эту статью, подключите к клоду гитхаб и напишите какую профессию хотите добавить. Возможно самая заморочка будет только с тг если вы в РФ, по поводу тг и как получить код, статью тоже писала https://habr.com/ru/articles/1047402/
ссылка на оригинал статьи https://habr.com/ru/articles/1083086/