Как создать агрегатор вакансий: источники, дедупликация и актуальность
Хороший агрегатор вакансий — это три инженерные задачи: где искать объявления, как их дедуплицировать и как поддерживать их актуальность. Решите их, и скрапинг станет легкой частью — вот план действий.
Агрегатор вакансий — это поисковая система для вакансий: он собирает объявления из множества источников и показывает их в одном месте. Сложности не в HTTP-запросах — они в выборе правильных источников, дедупликации одной и той же вакансии, которая появляется на пяти сайтах, и поддержании актуальности, чтобы не показывать роли, которые были заняты в прошлом месяце. Сделайте эти три вещи правильно, и у вас будет защищенный продукт; сделайте их неправильно, и у вас будет устаревшая, полная дубликатов лента, которая подрывает доверие. Это руководство — инженерный план: смешение источников, каноническая дедупликация, актуальность, вертикаль SERP вакансий и правовые границы, которые нужно уважать. Это информационное руководство, а не юридическая консультация.
Источник уровня 1: публичные конечные точки ATS
Самые чистые данные о вакансиях в интернете находятся не на досках объявлений — они на страницах карьеры компаний, работающих на системах управления кандидатами, большинство из которых предоставляют структурированные JSON. Greenhouse, Lever, Ashby, BambooHR, iCIMS, Paylocity и Workday предоставляют объявления, которые можно запросить напрямую, без парсинга HTML. Открытый агрегатор, который собирает данные со всех семи, делает это параллельно и настраивает количество рабочих процессов в соответствии с лимитами каждой платформы — примерно 50 одновременно для Workday, 30 для Greenhouse/Lever/iCIMS, 10 для BambooHR и 5 для самых строгих ограничителей. Этот уровень дает вам канонические названия, местоположения, диапазоны зарплат и URL-адреса для подачи заявки прямо от работодателя, что делает его основой любого серьезного агрегатора.
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 может выявить десятки тысяч идентификаторов компаний. Этот процесс обнаружения сам по себе является задачей скрапинга; направьте его через пул прокси-центров обработки данных, так как индекс терпим, и скорость здесь важнее, чем репутация IP.
Источник уровня 2: вертикаль SERP вакансий
Потоки ATS пропускают все, что размещено только на сайтах агрегаторов, региональных досках или в собственном опыте работы с вакансиями Google. Эффективный способ покрыть этот длинный хвост без скрапинга дюжины досок по отдельности — это вертикаль SERP вакансий — структурированный запрос, который возвращает вакансии, которые Google показывает для роли и местоположения, уже нормализованные. Наш SERP API предоставляет вертикаль вакансий наряду с новостями, изображениями и покупками, так что вы можете извлекать объявления о ролях по ключевому слову и гео как JSON и интегрировать их в тот же конвейер:
import httpx
def fetch_jobs_serp(query: str, location: str) -> list[dict]:
r = httpx.get(
"https://api.quantumproxies.io/serp",
params={"engine": "google_jobs", "q": query,
"location": location, "api_key": "QP_API_KEY"},
timeout=30,
)
jobs = r.json().get("jobs", [])
return [{
"source": "jobs_serp",
"external_id": j.get("job_id"),
"title": j.get("title"),
"company": j.get("company_name"),
"location": j.get("location"),
"apply_url": (j.get("apply_options") or [{}])[0].get("link"),
} for j in jobs]
serp_rows = fetch_jobs_serp("react developer", "Austin, TX")
Запускайте один и тот же запрос по целевым городам по расписанию, и у вас будет гео-покрытие, которое не предоставляет ни один поток ATS. Поскольку результаты SERP меняются в зависимости от местоположения, гео-направляйте каждый запрос — наш пост о том, как работает скрапинг SERP в 2026 году, охватывает механику гео и пагинации.
Извлеките вертикаль вакансий из SERP API

Дедупликация по каноническому ключу
Одна и та же вакансия регулярно появляется на сайте компании, двух агрегаторах и карточке вакансий Google. Показ ее четыре раза — самый быстрый способ выглядеть сломанным. Стандартное решение — канонический ключ: нормализуйте и хэшируйте комбинацию названия вакансии, компании, местоположения и — когда доступно — внешнего ID вакансии источника. Приведите к нижнему регистру, удалите пунктуацию и сократите пробелы перед хэшированием, чтобы "Sr. Software Engineer" и "senior software engineer" объединились.
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 дней является разумным значением по умолчанию, короче для быстро меняющихся рынков. Отслеживайте временную метку последнего просмотра для каждого источника и ежедневный счет, чтобы вы могли заметить, когда источник молча ломается; агрегатор, который следит за своим объемом, может открыть предупреждение в момент, когда числа платформы резко падают. Наша заметка о запуске скраперов как производственного программного обеспечения охватывает планирование, обнаружение дрейфа и оповещения.
Правовые границы, которые нужно уважать
Данные о вакансиях — это то место, где законы о скрапинге становятся реальными, потому что объявления могут содержать личные данные (имена рекрутеров, контактные данные), а подробные описания могут быть защищены авторским правом. Французский орган по защите данных оштрафовал компанию KASPR на €240,000 за скрапинг контактных данных LinkedIn без надлежащего согласия; штрафы за нарушение GDPR могут достигать €20 миллионов или 4% от мирового оборота, а убытки за нарушение авторских прав в США доходили до $150,000 за работу. Более безопасная позиция — структурная: предпочтение авторизованным потокам ATS и вертикали SERP вакансий перед грубой силой взлома досок с логином, хранение фактических полей (название, компания, местоположение) вместо повторной публикации полных защищенных авторским правом описаний и удаление личных данных, которые вам не нужны. Наш обзор законности веб-скрапинга в 2026 году и сага о соблюдении требований LinkedIn идут глубже.

Где прокси подходят
Уровень ATS редко нуждается в резидентных IP, но скрапинг обнаружения, вертикаль SERP и любой прямой скрапинг досок нуждаются — Google и более крупные доски ограничивают по IP и гео-вариантам своих результатов. Направьте их через вращающиеся резидентные прокси с ротацией на каждый запрос и гео-направлением, чтобы каждый запрос города исходил из соответствующего местоположения. Держите уровни отдельно: дешевые центры обработки данных для терпимого индекса, резидентные для чувствительных целей.
Часто задаваемые вопросы
Что такое агрегатор вакансий?
Это поисковая система для вакансий, которая собирает объявления из множества источников — страниц карьеры компаний, платформ ATS, других досок и SERP вакансий — нормализует их в одну схему, удаляет дубликаты и представляет их соискателям в одном поисковом месте. Инженерная работа заключается в поиске источников, дедупликации и актуальности, а не только в скрапинге.
Как вы дедуплицируете объявления о вакансиях из нескольких источников?
Создайте канонический ключ, нормализуя и хэшируя название вакансии, компанию, местоположение и внешний ID вакансии источника. Приведите к нижнему регистру, удалите пунктуацию и сократите пробелы сначала, чтобы варианты написания объединились. Сохраните первое вхождение и удалите совпадения. Это ловит одну и ту же роль, появляющуюся на сайте работодателя, агрегаторах и Google jobs.
Законно ли скрапить доски вакансий?
Это зависит от источника, данных и вашей юрисдикции. Публичные фактические поля объявлений имеют меньший риск, чем личные данные или полные защищенные авторским правом описания, и обход стен логина увеличивает риск по CFAA. Авторизованные потоки ATS и вертикаль SERP — это более чистые маршруты. Компании были сильно оштрафованы за скрапинг личных данных — получите юридическую консультацию для коммерческого использования.
Насколько свежими должны быть агрегированные данные о вакансиях?
Повторно извлекайте источники с высоким объемом, такие как потоки ATS, ежечасно, а длинный хвост ежедневно, затем удаляйте любое объявление, которое вы не видели повторно в скользящем окне — 30 дней является общим значением по умолчанию. Отслеживайте временную метку последнего просмотра для каждой вакансии и контролируйте объем по источнику, чтобы поймать сломанный источник до того, как пользователи увидят устаревшие роли.
Относитесь к агрегации как к трем проблемам — источники, дедупликация, актуальность — и скрапинг становится поддерживающей деталью. Начните с чистых потоков ATS и вертикали SERP вакансий, дедуплицируйте по каноническому ключу, активно удаляйте устаревшие данные и держите чувствительные скрапинги на вращающихся резидентных IP. Это разница между продуктом, которому доверяют, и кладбищем мертвых ссылок.