# Как создать агрегатор вакансий: источники, дедупликация и актуальность

Хороший агрегатор вакансий — это три инженерные задачи: где искать объявления, как их дедуплицировать и как поддерживать их актуальность. Решите их, и скрапинг станет легкой частью — вот план действий.

Агрегатор вакансий — это поисковая система для вакансий: он собирает объявления из множества источников и показывает их в одном месте. Сложности не в HTTP-запросах — они в выборе правильных источников, дедупликации одной и той же вакансии, которая появляется на пяти сайтах, и поддержании актуальности, чтобы не показывать роли, которые были заняты в прошлом месяце. Сделайте эти три вещи правильно, и у вас будет защищенный продукт; сделайте их неправильно, и у вас будет устаревшая, полная дубликатов лента, которая подрывает доверие. Это руководство — инженерный план: смешение источников, каноническая дедупликация, актуальность, вертикаль SERP вакансий и правовые границы, которые нужно уважать. Это информационное руководство, а не юридическая консультация.

## Источник уровня 1: публичные конечные точки ATS

Самые чистые данные о вакансиях в интернете находятся не на досках объявлений — они на страницах карьеры компаний, работающих на системах управления кандидатами, большинство из которых предоставляют структурированные JSON. Greenhouse, Lever, Ashby, BambooHR, iCIMS, Paylocity и Workday предоставляют объявления, которые можно запросить напрямую, без парсинга HTML. Открытый агрегатор, который собирает данные со всех семи, делает это параллельно и настраивает количество рабочих процессов в соответствии с лимитами каждой платформы — примерно 50 одновременно для Workday, 30 для Greenhouse/Lever/iCIMS, 10 для BambooHR и 5 для самых строгих ограничителей. Этот уровень дает вам канонические названия, местоположения, диапазоны зарплат и URL-адреса для подачи заявки прямо от работодателя, что делает его основой любого серьезного агрегатора.

```python
import httpx

# Greenhouse exposes a public board JSON endpoint per company slug
def fetch_greenhouse(slug: str) -> list[dict]:
    url = f"https://boards-api.greenhouse.io/v1/boards/{slug}/jobs?content=true"
    r = httpx.get(url, timeout=20)
    r.raise_for_status()
    jobs = r.json().get("jobs", [])
    return [{
        "source": "greenhouse",
        "external_id": str(j["id"]),
        "title": j["title"],
        "company": slug,
        "location": (j.get("location") or {}).get("name"),
        "apply_url": j["absolute_url"],
        "updated_at": j.get("updated_at"),
    } for j in jobs]

rows = fetch_greenhouse("examplecompany")
print(len(rows), "roles")
```

Чтобы найти компании для опроса, собирайте ATS слуги в масштабе из веб-индекса, а не вручную — сканирование архивов URL Common Crawl на шаблоны доменов ATS может выявить десятки тысяч идентификаторов компаний. Этот процесс обнаружения сам по себе является задачей скрапинга; направьте его через пул [прокси-центров обработки данных](https://quantumproxies.io/datacenter-proxies), так как индекс терпим, и скорость здесь важнее, чем репутация IP.

## Источник уровня 2: вертикаль SERP вакансий

Потоки ATS пропускают все, что размещено только на сайтах агрегаторов, региональных досках или в собственном опыте работы с вакансиями Google. Эффективный способ покрыть этот длинный хвост без скрапинга дюжины досок по отдельности — это вертикаль SERP вакансий — структурированный запрос, который возвращает вакансии, которые Google показывает для роли и местоположения, уже нормализованные. Наш [SERP API](https://quantumproxies.io/serp-api) предоставляет вертикаль вакансий наряду с новостями, изображениями и покупками, так что вы можете извлекать объявления о ролях по ключевому слову и гео как JSON и интегрировать их в тот же конвейер:

```python
import httpx

def fetch_jobs_serp(query: str, location: str) -> list[dict]:
    r = httpx.post(
        "https://api.quantumproxies.io/v1/scraper/serp",
        headers={"Authorization": "Bearer QP_API_KEY"},
        json={"query": query, "search_type": "jobs", "location": location},
        timeout=120,
    )
    jobs = r.json()["payload"].get("jobs_results", [])
    return [{
        "source": "jobs_serp",
        "title": j.get("title"),
        "company": j.get("company"),
        "location": j.get("location"),
        "apply_url": j.get("link"),
    } for j in jobs]

serp_rows = fetch_jobs_serp("react developer", "Austin, TX")
```

Запускайте один и тот же запрос по целевым городам по расписанию, и у вас будет гео-покрытие, которое не предоставляет ни один поток ATS. Поскольку результаты SERP меняются в зависимости от местоположения, гео-направляйте каждый запрос — наш пост о [том, как работает скрапинг SERP в 2026 году](https://quantumproxies.io/blog/how-serp-scraping-works-in-2026), охватывает механику гео и пагинации.

[Извлеките вертикаль вакансий из SERP API](https://quantumproxies.io/serp-api)

![Конвейер агрегатора вакансий в пять шагов: забирать вакансии из API ATS, SERP вакансий и напрямую с досок объявлений, нормализовать их в одну схему, удалять дубликаты по каноническому ключу, повторно загружать по расписанию и убирать устаревшие вакансии. Карточка дает правила: хешировать название, компанию, локацию и ID, обновлять ежечасно или ежедневно, удалять через 30 дней.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335191/blog/generated/qp-b9-059-diag1.png)
*Три уровня источников питают одну схему; дедупликация и окно актуальности превращают сырые объявления в надежный агрегатор.*

## Дедупликация по каноническому ключу

Одна и та же вакансия регулярно появляется на сайте компании, двух агрегаторах и карточке вакансий Google. Показ ее четыре раза — самый быстрый способ выглядеть сломанным. Стандартное решение — канонический ключ: нормализуйте и хэшируйте комбинацию названия вакансии, компании, местоположения и — когда доступно — внешнего ID вакансии источника. Приведите к нижнему регистру, удалите пунктуацию и сократите пробелы перед хэшированием, чтобы "Sr. Software Engineer" и "senior software engineer" объединились.

```python
import re, hashlib

def canonical_key(job: dict) -> str:
    def norm(s):
        return re.sub(r"[^a-z0-9]+", " ", (s or "").lower()).strip()
    basis = "|".join([
        norm(job.get("title")),
        norm(job.get("company")),
        norm(job.get("location")),
        (job.get("external_id") or ""),
    ])
    return hashlib.sha1(basis.encode()).hexdigest()

def dedupe(rows: list[dict]) -> list[dict]:
    seen, out = set(), []
    for job in rows:
        k = canonical_key(job)
        if k not in seen:
            seen.add(k)
            out.append(job)
    return out
```

## Актуальность — это функция, а не последняя мысль

Достоверность доски вакансий — это ее актуальность. Два механизма поддерживают ее честность: повторно извлекайте каждый источник по расписанию (ежечасно для потоков ATS с высоким объемом, ежедневно для длинного хвоста) и удаляйте все, что вы не видели повторно в скользящем окне — 30 дней является разумным значением по умолчанию, короче для быстро меняющихся рынков. Отслеживайте временную метку последнего просмотра для каждого источника и ежедневный счет, чтобы вы могли заметить, когда источник молча ломается; агрегатор, который следит за своим объемом, может открыть предупреждение в момент, когда числа платформы резко падают. Наша заметка о [запуске скраперов как производственного программного обеспечения](https://quantumproxies.io/blog/schedule-monitor-web-scrapers) охватывает планирование, обнаружение дрейфа и оповещения.

## Правовые границы, которые нужно уважать

Данные о вакансиях — это то место, где законы о скрапинге становятся реальными, потому что объявления могут содержать личные данные (имена рекрутеров, контактные данные), а подробные описания могут быть защищены авторским правом. Французский орган по защите данных оштрафовал компанию KASPR на €240,000 за скрапинг контактных данных LinkedIn без надлежащего согласия; штрафы за нарушение GDPR могут достигать €20 миллионов или 4% от мирового оборота, а убытки за нарушение авторских прав в США доходили до $150,000 за работу. Более безопасная позиция — структурная: предпочтение авторизованным потокам ATS и вертикали SERP вакансий перед грубой силой взлома досок с логином, хранение фактических полей (название, компания, местоположение) вместо повторной публикации полных защищенных авторским правом описаний и удаление личных данных, которые вам не нужны. Наш обзор [законности веб-скрапинга в 2026 году](https://quantumproxies.io/blog/is-web-scraping-legal-2026) и сага [о соблюдении требований LinkedIn](https://quantumproxies.io/blog/linkedin-public-data-scraping-compliance) идут глубже.

![Параллельные воркеры, настроенные под лимиты каждой платформы ATS: около 50 для Workday, 30 для Greenhouse, Lever и iCIMS, 10 для BambooHR и 5 для самых строгих. Карточка перечисляет цифры за этим: семь платформ ATS, 30-дневное окно актуальности и штраф KASPR в 240 000 евро за скрапинг контактных данных LinkedIn.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335191/blog/generated/qp-b9-059-diag2.png)
*Структурированные потоки ATS плюс каноническая дедупликация превосходят грубый HTML-скрапинг по стоимости, охвату и юридической безопасности.*

## Где прокси подходят

Уровень ATS редко нуждается в резидентных IP, но скрапинг обнаружения, вертикаль SERP и любой прямой скрапинг досок нуждаются — Google и более крупные доски ограничивают по IP и гео-вариантам своих результатов. Направьте их через [вращающиеся резидентные прокси](https://quantumproxies.io/rotating-proxies) с ротацией на каждый запрос и гео-направлением, чтобы каждый запрос города исходил из соответствующего местоположения. Держите уровни отдельно: дешевые центры обработки данных для терпимого индекса, резидентные для чувствительных целей.

## Часто задаваемые вопросы

### Что такое агрегатор вакансий?

Это поисковая система для вакансий, которая собирает объявления из множества источников — страниц карьеры компаний, платформ ATS, других досок и SERP вакансий — нормализует их в одну схему, удаляет дубликаты и представляет их соискателям в одном поисковом месте. Инженерная работа заключается в поиске источников, дедупликации и актуальности, а не только в скрапинге.

### Как вы дедуплицируете объявления о вакансиях из нескольких источников?

Создайте канонический ключ, нормализуя и хэшируя название вакансии, компанию, местоположение и внешний ID вакансии источника. Приведите к нижнему регистру, удалите пунктуацию и сократите пробелы сначала, чтобы варианты написания объединились. Сохраните первое вхождение и удалите совпадения. Это ловит одну и ту же роль, появляющуюся на сайте работодателя, агрегаторах и Google jobs.

### Законно ли скрапить доски вакансий?

Это зависит от источника, данных и вашей юрисдикции. Публичные фактические поля объявлений имеют меньший риск, чем личные данные или полные защищенные авторским правом описания, и обход стен логина увеличивает риск по CFAA. Авторизованные потоки ATS и вертикаль SERP — это более чистые маршруты. Компании были сильно оштрафованы за скрапинг личных данных — получите юридическую консультацию для коммерческого использования.

### Насколько свежими должны быть агрегированные данные о вакансиях?

Повторно извлекайте источники с высоким объемом, такие как потоки ATS, ежечасно, а длинный хвост ежедневно, затем удаляйте любое объявление, которое вы не видели повторно в скользящем окне — 30 дней является общим значением по умолчанию. Отслеживайте временную метку последнего просмотра для каждой вакансии и контролируйте объем по источнику, чтобы поймать сломанный источник до того, как пользователи увидят устаревшие роли.

Относитесь к агрегации как к трем проблемам — источники, дедупликация, актуальность — и скрапинг становится поддерживающей деталью. Начните с чистых потоков ATS и вертикали SERP вакансий, дедуплицируйте по каноническому ключу, активно удаляйте устаревшие данные и держите чувствительные скрапинги на вращающихся резидентных IP. Это разница между продуктом, которому доверяют, и кладбищем мертвых ссылок.

[Запитайте ваш агрегатор с помощью Scraper API](https://quantumproxies.io/scraper-api)
