# Como Construir um Agregador de Vagas de Emprego: Fontes, Deduplicação e Atualização

Um bom agregador de vagas é composto por três problemas de engenharia: onde obter as listagens, como deduplicá-las e como mantê-las atualizadas. Resolva esses problemas e a raspagem se torna a parte fácil — aqui está o plano.

Um agregador de vagas de emprego é um motor de busca para anúncios de emprego: ele coleta listagens de várias fontes e as exibe em um só lugar. As partes difíceis não são os pedidos HTTP — são escolher as fontes certas, deduplicar o mesmo emprego que aparece em cinco sites e manter tudo atualizado para que você não mostre cargos preenchidos no mês passado. Acertar esses três pontos e você terá um produto defensável; errar e você terá um feed obsoleto e cheio de duplicatas que corrói a confiança. Este guia é o plano de engenharia: mistura de fontes, deduplicação canônica, atualização, o vertical de SERP de empregos e as linhas legais a respeitar. É informativo, não um conselho legal.

## Fonte nível 1: endpoints públicos de ATS

Os dados de emprego mais limpos na internet não estão em quadros de empregos — estão nas páginas de carreiras das empresas alimentadas por sistemas de rastreamento de candidatos, a maioria dos quais expõe JSON estruturado. Greenhouse, Lever, Ashby, BambooHR, iCIMS, Paylocity e Workday todos fornecem listagens que você pode solicitar diretamente, sem análise de HTML. Um agregador de código aberto que puxa de todos os sete os busca em paralelo e ajusta as contagens de trabalhadores aos limites de taxa de cada plataforma — aproximadamente 50 simultâneos para Workday, 30 para Greenhouse/Lever/iCIMS, 10 para BambooHR e 5 para os limitadores mais restritivos. Este nível fornece títulos canônicos, locais, faixas salariais e URLs de aplicação diretamente do empregador, o que o torna a espinha dorsal de qualquer agregador sério.

```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")
```

Para encontrar empresas para consultar, colete slugs de ATS em escala a partir de um índice da web em vez de manualmente — escanear os arquivos de URL do Common Crawl em busca de padrões de domínio de ATS pode revelar dezenas de milhares de identificadores de empresas. Essa varredura de descoberta é em si um trabalho de raspagem; direcione-a através de um pool de [proxy de datacenter](https://quantumproxies.io/datacenter-proxies) já que o índice é leniente e a velocidade importa mais do que a reputação do IP lá.

## Fonte nível 2: o vertical de SERP de empregos

Os feeds de ATS perdem tudo o que é postado apenas em sites agregadores, quadros regionais ou na própria experiência de empregos do Google. A maneira eficiente de cobrir esse longo rabo sem raspar uma dúzia de quadros individualmente é o vertical de SERP de empregos — uma consulta estruturada que retorna os empregos que o Google exibe para um cargo e localização, já normalizados. Nossa [SERP API](https://quantumproxies.io/serp-api) expõe um vertical de empregos junto com notícias, imagens e compras, para que você possa puxar listagens de cargos por palavra-chave e localização como JSON e integrá-las no mesmo pipeline:

```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")
```

Execute a mesma consulta nas cidades-alvo em uma programação e você terá cobertura geográfica que nenhum feed de ATS único fornece. Como os resultados de SERP mudam por localização, direcione geograficamente cada consulta — nosso post sobre [como a raspagem de SERP funciona em 2026](https://quantumproxies.io/blog/how-serp-scraping-works-in-2026) cobre as mecânicas de geolocalização e paginação.

[Puxe o vertical de empregos da SERP API](https://quantumproxies.io/serp-api)

![O pipeline de um agregador de vagas em cinco etapas: puxar anúncios de APIs de ATS, da SERP de vagas e de sites diretos, normalizá-los em um único esquema, deduplicar por uma chave canônica, buscar de novo segundo uma agenda e remover vagas desatualizadas. O quadro dá as regras: hash de título, empresa, local e ID, nova busca a cada hora ou dia, remoção após 30 dias.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335191/blog/generated/qp-b9-059-diag1.png)
*Três níveis de fonte alimentam um esquema; deduplicação e uma janela de atualização transformam listagens brutas em um agregador confiável.*

## Deduplicação por chave canônica

O mesmo emprego aparece rotineiramente no site da empresa, em dois agregadores e em um cartão de empregos do Google. Mostrá-lo quatro vezes é a maneira mais rápida de parecer quebrado. A correção padrão é uma chave canônica: normalize e faça o hash da combinação de título do emprego, empresa, localização e — quando disponível — o ID externo do emprego da fonte. Converta para minúsculas, remova pontuação e colapse espaços em branco antes de fazer o hash para que "Engenheiro de Software Sênior" e "engenheiro de software sênior" se unam.

```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
```

## Atualização é uma característica, não um pensamento posterior

A credibilidade de um quadro de empregos é sua atualização. Dois mecanismos a mantêm honesta: reobtenha cada fonte em uma programação (horária para feeds de ATS de alto volume, diária para o longo rabo), e elimine qualquer coisa que você não tenha revisto em uma janela contínua — 30 dias é um padrão sensato, mais curto para mercados de rápida movimentação. Acompanhe um carimbo de data/hora de última visualização por fonte e uma contagem diária para que você possa identificar quando uma fonte quebra silenciosamente; um agregador que monitora seu próprio volume pode abrir um alerta no momento em que os números de uma plataforma caem drasticamente. Nossa nota sobre [executar raspadores como software de produção](https://quantumproxies.io/blog/schedule-monitor-web-scrapers) cobre agendamento, detecção de desvio e alertas.

## As linhas legais a respeitar

Dados de emprego são onde a lei de raspagem se torna real, porque anúncios podem conter dados pessoais (nomes de recrutadores, detalhes de contato) e descrições detalhadas são protegidas por direitos autorais. A autoridade de proteção de dados da França multou a empresa KASPR em €240.000 por raspar dados de contato do LinkedIn sem o devido consentimento; as penalidades do GDPR podem chegar a €20 milhões ou 4% do faturamento global, e os danos por direitos autorais chegaram a $150.000 por obra em casos nos EUA. A postura mais segura é estrutural: prefira feeds de ATS autorizados e o SERP de empregos em vez de forçar a entrada em quadros protegidos por login, armazene campos factuais (título, empresa, localização) em vez de republicar descrições completas protegidas por direitos autorais, e remova dados pessoais que você não precisa. Nossa visão geral sobre [legalidade da raspagem de web em 2026](https://quantumproxies.io/blog/is-web-scraping-legal-2026) e a saga de [conformidade do LinkedIn](https://quantumproxies.io/blog/linkedin-public-data-scraping-compliance) vão mais a fundo.

![Workers simultâneos ajustados aos limites de taxa de cada plataforma de ATS: cerca de 50 para Workday, 30 para Greenhouse, Lever e iCIMS, 10 para BambooHR e 5 para as mais restritivas. O quadro lista os números por trás disso: sete plataformas de ATS, uma janela de atualidade de 30 dias e a multa de €240.000 à KASPR por coletar dados de contato do LinkedIn.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335191/blog/generated/qp-b9-059-diag2.png)
*Feeds estruturados de ATS mais deduplicação canônica superam a raspagem de HTML por força bruta em custo, cobertura e exposição legal.*

## Onde os proxies se encaixam

O nível de ATS raramente precisa de IPs residenciais, mas a varredura de descoberta, o vertical de SERP e qualquer raspagem direta de quadros precisam — Google e os maiores quadros limitam por IP e variam seus resultados por localização. Direcione esses através de [proxies residenciais rotativos](https://quantumproxies.io/rotating-proxies) com rotação por solicitação e direcionamento geográfico para que cada consulta de cidade venha de uma localização correspondente. Mantenha os níveis separados: datacenter barato para o índice leniente, residencial para os alvos sensíveis.

## Perguntas frequentes

### O que é um agregador de vagas de emprego?

É um motor de busca para anúncios de emprego que coleta listagens de várias fontes — páginas de carreiras de empresas, plataformas de ATS, outros quadros e o SERP de empregos — normaliza-os em um único esquema, remove duplicatas e os apresenta aos candidatos em um único local pesquisável. O trabalho de engenharia está na obtenção de fontes, deduplicação e atualização, não apenas na raspagem.

### Como você deduplica listagens de emprego de várias fontes?

Construa uma chave canônica normalizando e fazendo o hash do título do emprego, empresa, localização e o ID externo do emprego da fonte. Converta para minúsculas, remova pontuação e colapse espaços em branco primeiro para que variações de grafia se unam. Mantenha a primeira ocorrência e descarte as correspondências. Isso captura o mesmo cargo aparecendo no site do empregador, agregadores e empregos do Google.

### É legal raspar quadros de empregos?

Depende da fonte, dos dados e da sua jurisdição. Campos de listagem factuais públicos têm menor risco do que dados pessoais ou descrições completas protegidas por direitos autorais, e contornar paredes de login aumenta a exposição ao estilo CFAA. Feeds de ATS autorizados e o SERP de empregos são as rotas mais limpas. Empresas foram multadas pesadamente por raspar dados pessoais — obtenha aconselhamento legal para uso comercial.

### Quão atualizados devem ser os dados de emprego agregados?

Reobtenha fontes de alto volume como feeds de ATS a cada hora e o longo rabo diariamente, depois elimine qualquer listagem que você não tenha revisto dentro de uma janela contínua — 30 dias é um padrão comum. Acompanhe um carimbo de data/hora de última visualização por emprego e monitore o volume por fonte para que você detecte uma fonte quebrada antes que os usuários vejam cargos obsoletos.

Trate a agregação como três problemas — fontes, deduplicação, atualização — e a raspagem se torna um detalhe de suporte. Comece com feeds limpos de ATS e o vertical de SERP de empregos, deduplique em uma chave canônica, elimine agressivamente e mantenha as varreduras sensíveis em IPs residenciais rotativos. Essa é a diferença entre um produto em que as pessoas confiam e um cemitério de links mortos.

[Alimente seu agregador com a Scraper API](https://quantumproxies.io/scraper-api)
