ideipro logotyp

Парсинг HH.ru: от /vacancies до асинхронных очередей и боли с ConversationHandler’ами

Привет, Хабр.

Думаю, у каждого, кто искал работу, есть этот «любимый» запрос на hh. Вбиваешь «Python Developer», ставишь фильтр «нет опыта», а тебе вываливается 500 вакансий «Senior Analyst», где в требованиях «базовое знание SQL, Python будет плюсом».

Ручной разбор этой каши убивает время и мотивацию. Мой друг Роман (он IT-рекрутер и карьерный консультант) постоянно рассказывает, как кандидаты выгорают еще до первого собеса именно на этом этапе.

Я решил, что хватит. Пора автоматизировать рутину. Казалось бы, 30-минутная задача: дернул API, отфильтровал, откликнулся. Как же я ошибался. Сегодня расскажу, на какие грабли наступил, пока пилил «Аврору» — свой инструмент для автоматизации этого ада.

Грабли №1: «Умный» поиск — это не text=…

Наивный старт: эндпоинт /vacancies с параметром text=»Python». Сразу нет.

Окей, усложняем. («QA» OR «Тестировщик») NOT («Junior» OR «Стажер»). Уже лучше, но составлять руками — боль.

Решение (частичное): Эндпоинт /resumes/{resume_id}/similar_vacancies. HH сам подбирает похожее. Чище, чем ручной поиск.

Новая проблема: А если резюме «на коленке»? Или человек хочет сменить профиль? similar_vacancies не сработает. Роман подтвердил: таких случаев полно, и простой поиск по резюме их отсекает.

Пришлось городить гибрид:

  1. Сначала similar_vacancies + кастомный query пользователя как доп. фильтр.

  2. Когда там все кончается, бесшовно переключаемся на /vacancies со всеми фильтрами и кастомным запросом.

В коде (hh_api_client.py) это async def search_and_apply_generator, который меняет search_stage с ‘similar’ на ‘general’. Это позволяет Авроре копать глубже, когда «идеальные» совпадения закончились.

Грабли №2: Настройка диалога — это конечный автомат

Самое сложное — заставить пользователя дать нужные данные в Telegram. Просто спросить «какой у вас график?» нельзя. Выбор «Офис/Гибрид» требует города, запрещает «Всю Россию», и так далее. Роман тоже говорил, что кандидаты часто путаются в фильтрах, поэтому интерфейс должен быть пуленепробиваемым.

Это — ад. Это — ConversationHandler из python-telegram-bot во всей красе. Машина состояний, где каждый CallbackQueryHandler решает, куда вести диалог дальше, и ловит ошибки через fallbacks.

На отладку этого ушло больше времени, чем на сам поиск.

Грабли №3: Отклик «замораживает» бота

Окей. Поиск есть, настройки есть. Пользователь жмет «Старт». Бот находит 100 вакансий. И начинает откликаться: API Gemini (LLM) за письмом (5-10 сек) -> API HH (/negotiations) с письмом (1-2 сек) -> Повторить 100 раз.

И все это время бот висит. 5 пользователей — сервис можно выключать.

Решение: PostgreSQL как очередь задач. Никаких asyncio.Queue в памяти.

  1. Команды просто кладут (user_id, vacancy_id, resume_id) в таблицу application_queue со статусом pending.

  2. Фоновый asyncio.Task (application_worker) пытается забрать задачу из БД.

  3. Как сделать, чтобы 5 инстансов бота не схватили одну задачу? FOR UPDATE SKIP LOCKED.

Этот SQL (database.py) — сердце воркера:

SQL

— database.py (функция get_next_pending_job) UPDATE application_queue SET status = ‘processing’ WHERE id = (SELECT id FROM application_queue WHERE status = ‘pending’ ORDER BY created_at LIMIT 1 FOR UPDATE SKIP LOCKED) RETURNING *;

Транзакция атомарно находит, блокирует, а если заблокировано — пропускает и ищет следующую. Потом меняет статус и возвращает. Воркер спокойно идет в Gemini, в HH API, и только потом (в finally) удаляет job или ставит error. Бот в Telegram при этом «летает».

Зачем все это?

Вся эта сложность — не самоцель. Она нужна, чтобы Аврора могла:

  • Находить вакансии точнее, чем стандартный поиск hh.ru (гибридный подход).

  • Не бесить пользователя сложными настройками (машина состояний).

  • Работать стабильно и быстро для сотен юзеров одновременно (асинхронная очередь).

  • Писать релевантные письма, потому что логику для LLM мы строили как раз на инсайтах Романа о том, что реально цепляет рекрутеров (это тема для отдельной статьи!).

То, что начиналось как скрипт на 50 строк, превратилось в сервис, который пытается немного починить сломанный процесс найма.

Прямо сейчас мы собрали первую фокус-группу (QA, DevOps/SRE, Senior Frontend, QA lead), которая тестирует Аврору. Собираем фидбэк, чтобы сделать ее еще лучше к релизу 7 ноября (да, мы планируем дать доступ первым 100 смельчакам).

Что думаете вы, Хабр? Автоматизация откликов — это необходимый инструмент для выживания на рынке, или мы просто выводим гонку вооружений на новый уровень?

Если сталкивались с похожими проблемами при работе с API HH или просто есть мысли на этот счет — буду рад обсудить в комментариях. Или залетайте в наш небольшой Telegram-канал, где мы делимся прогрессом и спорим о будущем поиска работы: https://t.me/AuroraCareer

Спасибо.

Источник: habr.com

✅ Найденные теги: новости, Парсинг

ОСТАВЬТЕ СВОЙ КОММЕНТАРИЙ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

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

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых