- PVSM.RU - https://www.pvsm.ru -
Всем привет!
Сегодня я расскажу, как наша студенческая команда из СПбПУ разработала систему для сбора и анализа данных о российском IT-рынке труда с помощью платформы hh.ru [1]. Вместо громоздкого монолита мы построили модульное асинхронное приложение на Python, сфокусировавшись на высокой производительности при массовом сборе данных, устойчивости к ошибкам и построении чёткого аналитического конвейера.
Если вам интересно, как эффективно собрать и обработать сотни тысяч записей из публичного API, построить отказоустойчивый пайплайн и сгенерировать аналитические отчёты — устраивайтесь поудобнее. Поехали!
Рынок IT-вакансий невероятно динамичен. Чтобы понимать реальные тренды — какие навыки востребованы, какие компании больше всего нанимают и какие зарплаты предлагают — нужны данные. Много данных. Нашей целью был переход от домыслов к фактам. Мы решили создать систему, которая могла бы автономно:
Собирать актуальные данные о вакансиях с hh.ru [1] через его публичный API.
Обрабатывать и очищать эти данные, устойчиво справляясь с ограничениями и ошибками API.
Надёжно хранить данные для анализа.
Выполнять сложные агрегации и генерировать визуальные отчёты по ключевым метрикам рынка.
Быть масштабируемой и поддерживаемой, позволяя расширять функциональность.
Мы выбрали модульную, сервис-ориентированную архитектуру на Python, потому что это позволило:
Чётко разделить ответственность (сбор данных, хранение, анализ, визуализация).
Масштабировать компоненты независимо (например, запускать несколько сборщиков данных).
Легко тестировать и отлаживать отдельные части системы.
Сделать проект легковесным и сфокусированным на его основной задаче — обработке данных.
Наша система построена по принципу чёткого разделения ответственности. Каждый модуль выполняет одну задачу и общается с другими через простые интерфейсы. Это классический пайплайн ETL (Extract, Transform, Load), адаптированный под особенности hh.ru [1] API.
Вот из каких ключевых компонентов состоит система:
Ядро системы (Python 3.10):
data_collector: Асинхронный сборщик данных, взаимодействующий с API hh.ru [1].
db_manager: Менеджер для работы с базой данных SQLite.
analytics: Модуль для анализа данных и генерации графиков.
models: Pydantic-модели для валидации и структурирования данных.
Вспомогательные технологии:
httpx: Для асинхронных HTTP-запросов к API.
pydantic: Для валидации и парсинга сырых JSON-данных в строгие модели.
pandas: Для оперативной агрегации и анализа данных в памяти.
matplotlib/seaborn: Для построения всех графиков и визуализаций.
SQLite: В качестве надёжного и лёгкого хранилища для структурированных данных.
Всё начинается с источника данных — публичного API hh.ru [1] (версия 1.0.0). Далее данные проходят несколько этапов:
Сбор и Валидация: Модуль collector асинхронно запрашивает вакансии. Полученный JSON проходит строгую проверку через Pydantic-модель Vacancy, которая отсеивает некорректные записи и приводит данные к единому формату. Только после этого данные попадают в Базу данных (SQLite).
Трансформация и Анализ: Модуль analyzer загружает данные из БД в pandas.DataFrame. Здесь происходит основная «магия»: группировка вакансий по ролям, расчёт медианных зарплат, подсчёт частоты навыков и анализ трендов.
Визуализация: На основе готовых датафреймов модуль infographics генерирует набор статических, но информативных графиков, готовых для включения в отчёт или дашборд.
Почему именно такой стек?
Асинхронность (httpx, asyncio): Критически важна для обхода тысяч страниц вакансий без многодневного ожидания.
Валидация (pydantic): Гарантирует целостность данных при сохранении. Мы точно знаем, что в БД попали только данные правильного формата.
SQLite: Для одноразового аналитического пайплайна с данными в ~500k записей — это идеальный выбор, работает быстро и надёжно.
pandas: Фактический стандарт для анализа табличных данных в Python. Позволяет за несколько строк кода выполнить сложные агрегации, на которых в SQL ушло бы гораздо больше времени.
Такой подход позволил нам создать не «чёрный ящик», а прозрачную, ремонтопригодную систему, где каждый этап обработки данных можно проверить и доработать.
Давайте заглянем под капот и посмотрим, как реализованы ключевые модули системы. Весь код доступен в нашем открытом репозитории на GitHub [2].
Сердце системы — модуль collector.py [3], который обходит API hh.ru [1]. Главные задачи: масштаб (сотни тысяч вакансий) и устойчивость (API имеет лимиты и может возвращать ошибки).
Ключевые решения:
Асинхронность: Используем asyncio и httpx для одновременной обработки множества запросов. Это ускорило сбор по сравнению с синхронным подходом.
Контроль ошибок: Система обрабатывает HTTP-ошибки 429 (слишком много запросов) и 403 (запрещено), делая паузы и логируя проблемные ID вакансий для повторной попытки.
Валидация на лету: Каждый полученный JSON-объект сразу проходит проверку через Pydantic-модель. Это защищает базу данных от "мусора".
# Упрощённый пример асинхронного запроса с обработкой ошибок
import httpx
from models.vacancy_model import Vacancy
async def fetch_vacancy(session: httpx.AsyncClient, vacancy_id: int) -> Vacancy | None:
url = f"https://api.hh.ru/vacancies/{vacancy_id}"
try:
response = await session.get(url, timeout=10.0)
response.raise_for_status()
# Парсинг и валидация через Pydantic
return Vacancy.parse_obj(response.json())
except httpx.HTTPStatusError as e:
if e.response.status_code == 404:
# Вакансия не найдена - это нормально, пропускаем
return None
logger.warning(f"HTTP error for {vacancy_id}: {e}")
return None
Pydantic-модель Vacancy — это строгий контракт, описывающий, как должны выглядеть наши данные. Она автоматически приводит типы (например, строку с зарплатой к числу) и отбрасывает лишние поля.
# Упрощённая схема модели Vacancy
from pydantic import BaseModel
class Vacancy(BaseModel):
id: int
name: str
salary_from: Optional[int] = None
salary_to: Optional[int] = None
employer_name: str
key_skills: Optional[str] = None
# ... другие поля
Работа с SQLite организована через модуль db_manager. Мы сознательно не использовали ORM, чтобы сохранить полный контроль над запросами и производительностью. Все взаимодействия с БД — через параметризованные SQL-запросы.
После загрузки данных из SQLite в pandas.DataFrame анализ становится простым и выразительным:
# Пример расчёта медианной зарплаты по ролям
import pandas as pd
def calculate_median_salaries(df: pd.DataFrame) -> pd.DataFrame:
# Создаём условную "среднюю" зарплату для анализа
df['salary_mid'] = df[['salary_from', 'salary_to']].mean(axis=1)
# Группируем по профессиональной роли и считаем медиану
median_by_role = df.groupby('professional_role')['salary_mid'].median()
return median_by_role.sort_values(ascending=False).head(15)
Модуль infographics.py [4] использует matplotlib и seaborn для превращения этих датафреймов в готовые для публикации графики. Мы создали единый стиль для всех графиков, чтобы визуализация выглядела профессионально.
Конфигурация через переменные окружения: Все чувствительные настройки (например, задержки между запросами) вынесены в private_settings.py [5], который не попадает в Git.
Детальное логирование: Каждый этап — от сбора до визуализации — подробно логируется. Это позволило легко отлаживать систему и понимать, на каком этапе возникла проблема.
Сбор данных: Обработка ~11 миллионов страниц вакансий для фильтрации 393 тысяч IT-вакансий заняла несколько суток непрерывной работы. Использование асинхронности позволило загружать CPU на 80-90%.
Аналитика: Расчёт всех метрик (топ навыков, зарплаты, распределение) для финального датасета занимает менее 5 минут на обычном ноутбуке.
Память: Пиковое использование памяти не превышает 2-3 ГБ благодаря потоковой обработке и эффективной работе pandas.
После нескольких суток непрерывного сбора данных и их обработки мы получили детальную картину российского IT-рынка на 2025 год. Вот какие инсайты удалось извлечь из 393 тысяч вакансий.
1. Концентрация рынка: всё решают гиганты
Анализ данных показал впечатляющую концентрацию спроса. На первую десятку компаний-работодателей (Сбер, Ozon, Яндекс, Т1 и другие) приходится свыше 70% всех IT-вакансий. Это говорит о том, что рынок в значительной степени формируется стратегиями найма крупнейших игроков.
2. «Обязательный минимум» разработчика универсален
Самые востребованные технические навыки оказались вполне предсказуемыми, но от этого не менее важными. Абсолютным лидером стал SQL (упоминался в десятках тысяч вакансий), за ним следуют Linux, Python, Git и PostgreSQL. Этот набор можно считать новым «джентльменским набором» IT-специалиста широкого профиля. Среди soft skills лидируют «Клиентская коммуникация» и «Аналитическое мышление».
3. Рынок труда для джуниоров сужается
Несмотря на общий объём вакансий, данные подтвердили тренд, о котором много пишут: сложный вход в IT для новичков. Большинство вакансий (около 96%) — на полную занятость, и более 82% требуют опыта работы от 1 года. Абсолютно доминирует формат полного рабочего дня в офисе (72.3%), в то время как доля полностью удалённых вакансий составляет около 23%.
4. Зарплаты: ожидаемая иерархия
Расчёт медианных зарплат подтвердил логику рынка. На верхушке находятся руководители направлений (250 000+ руб.) и DevOps-инженеры (215 000+ руб.). Специалисты в области Data Science и системные аналитики также входят в топ с зарплатами от 200 000 руб. Интересно, что разрыв между middle и senior-уровнем во многих специализациях не такой большой, как между junior и middle.
Начинающим data-инженерам и дата-сайентистам: Весь код в открытом доступе и может служить учебным примером построения end-to-end ETL/ELT пайплайна на Python.
HR-специалистам и аналитикам рынка: Методология и готовые скрипты могут быть адаптированы для конкурентного анализа или исследования нишевых сегментов рынка.
Студентам и исследователям: Полученный датасет и код для его анализа — отличная основа для научных работ или курсовых проектов в области экономики труда или компьютерных наук.
Исходный код проекта доступен на GitHub [2]
Если у вас есть вопросы по реализации, предложения по улучшению кода или идеи для совместного исследования — добро пожаловать в issues или дискуссии в репозитории!
Автор: Elizaveta_Golovach
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/439735
Ссылки в тексте:
[1] hh.ru: http://hh.ru
[2] открытом репозитории на GitHub: https://github.com/sunshineinabagg/hh_analytics.git
[3] collector.py: http://collector.py
[4] infographics.py: http://infographics.py
[5] settings.py: http://settings.py
[6] Источник: https://habr.com/ru/articles/979118/?utm_source=habrahabr&utm_medium=rss&utm_campaign=979118
Нажмите здесь для печати.