Jak zbudować agregator ofert pracy: źródła, deduplikacja i aktualność

Dobry agregator ofert pracy to trzy problemy inżynieryjne: skąd pozyskiwać oferty, jak je deduplikować i jak utrzymywać ich aktualność. Rozwiąż te kwestie, a scraping będzie łatwą częścią — oto plan działania.

Agregator ofert pracy to wyszukiwarka ofert pracy: pobiera oferty z wielu źródeł i pokazuje je w jednym miejscu. Trudności nie stanowią zapytania HTTP — to wybór odpowiednich źródeł, deduplikacja tej samej oferty pojawiającej się na pięciu stronach i utrzymanie aktualności, aby nie pokazywać ról, które zostały obsadzone w zeszłym miesiącu. Jeśli zrobisz to dobrze, masz produkt, któremu można zaufać; jeśli nie, masz przestarzały, pełen duplikatów kanał, który niszczy zaufanie. Ten przewodnik to plan inżynieryjny: mieszanka źródeł, deduplikacja kanoniczna, aktualność, pion SERP ofert pracy i granice prawne, które należy respektować. Jest to informacyjne, a nie porada prawna.

Źródło poziom 1: publiczne punkty końcowe ATS

Najczystsze dane o ofertach pracy w internecie nie znajdują się na tablicach ogłoszeń — są na stronach karier firm zasilanych przez systemy śledzenia aplikacji, z których większość udostępnia ustrukturyzowany JSON. Greenhouse, Lever, Ashby, BambooHR, iCIMS, Paylocity i Workday wszystkie udostępniają oferty, które można pobierać bezpośrednio, bez parsowania HTML. Agregator open-source, który pobiera dane z wszystkich siedmiu, pobiera je równolegle i dostosowuje liczbę pracowników do limitów szybkości każdej platformy — około 50 równocześnie dla Workday, 30 dla Greenhouse/Lever/iCIMS, 10 dla BambooHR i 5 dla najbardziej restrykcyjnych ograniczeń. Ten poziom daje kanoniczne tytuły, lokalizacje, przedziały wynagrodzeń i URL-e aplikacji bezpośrednio od pracodawcy, co czyni go kręgosłupem każdego poważnego agregatora.

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

Aby znaleźć firmy do sondowania, zbieraj slugsy ATS na dużą skalę z indeksu sieciowego, a nie ręcznie — skanowanie archiwów URL Common Crawl pod kątem wzorców domen ATS może ujawnić dziesiątki tysięcy identyfikatorów firm. To odkrywcze crawl to samo w sobie zadanie scrapingu; przekieruj je przez pulę proxy centrum danych, ponieważ indeks jest łagodny, a szybkość jest ważniejsza niż reputacja IP.

Źródło poziom 2: pion SERP ofert pracy

Kanały ATS pomijają wszystko, co jest publikowane tylko na stronach agregatorów, regionalnych tablicach lub w doświadczeniu ofert pracy Google. Efektywnym sposobem na pokrycie tego długiego ogona bez scrapowania tuzina tablic indywidualnie jest pion SERP ofert pracy — ustrukturyzowane zapytanie, które zwraca oferty pracy, które Google pokazuje dla roli i lokalizacji, już znormalizowane. Nasze SERP API udostępnia pion ofert pracy obok wiadomości, obrazów i zakupów, dzięki czemu można pobierać oferty ról według słowa kluczowego i geolokalizacji jako JSON i włączać je do tej samej ścieżki przetwarzania:

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

Uruchom to samo zapytanie w docelowych miastach według harmonogramu, a uzyskasz pokrycie geograficzne, którego nie zapewnia żaden pojedynczy kanał ATS. Ponieważ wyniki SERP zmieniają się w zależności od lokalizacji, geotargetuj każde zapytanie — nasz post na temat jak działa scraping SERP w 2026 obejmuje mechanikę geolokalizacji i paginacji.

Pobierz pion ofert pracy z SERP API

Diagram ścieżki przetwarzania pokazujący dane o ofertach pracy pozyskiwane z ATS APIs, SERP ofert pracy i bezpośrednich tablic, następnie normalizowane, deduplikowane i odświeżane
Trzy poziomy źródeł zasilają jeden schemat; deduplikacja i okno aktualności przekształcają surowe oferty w godny zaufania agregator.

Dedup za pomocą klucza kanonicznego

Ta sama oferta pracy rutynowo pojawia się na stronie firmy, dwóch agregatorach i karcie ofert pracy Google. Pokazywanie jej cztery razy to najszybszy sposób na wyglądanie na zepsutą. Standardowym rozwiązaniem jest klucz kanoniczny: normalizuj i haszuj kombinację tytułu pracy, firmy, lokalizacji i — gdy jest dostępny — zewnętrznego ID oferty źródła. Zamień na małe litery, usuń interpunkcję i zredukuj białe znaki przed haszowaniem, aby "Sr. Software Engineer" i "senior software engineer" zredukowały się do jednego.

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

Aktualność to cecha, a nie przemyślenie

Wiarygodność tablicy ofert pracy to jej aktualność. Dwa mechanizmy utrzymują ją w uczciwości: ponowne pobieranie każdego źródła według harmonogramu (co godzinę dla kanałów ATS o dużej objętości, codziennie dla długiego ogona) i usuwanie wszystkiego, czego nie widziałeś ponownie w oknie przesuwnym — 30 dni to rozsądna domyślna wartość, krótsza dla szybko zmieniających się rynków. Śledź znacznik czasu ostatniego widzenia na źródło i dzienną liczbę, aby można było zauważyć, kiedy źródło cicho się psuje; agregator, który monitoruje własną objętość, może otworzyć alert w momencie, gdy liczby platformy spadną drastycznie. Nasza notatka na temat uruchamiania scraperów jako oprogramowania produkcyjnego obejmuje harmonogramowanie, wykrywanie dryfu i alertowanie.

Granice prawne, które należy respektować

Dane o ofertach pracy to miejsce, gdzie prawo dotyczące scrapingu staje się rzeczywiste, ponieważ oferty mogą zawierać dane osobowe (nazwiska rekruterów, dane kontaktowe), a szczegółowe opisy są chronione prawem autorskim. Francuski organ ochrony danych nałożył na firmę KASPR karę w wysokości 240 000 € za scrapowanie danych kontaktowych LinkedIn bez odpowiedniej zgody; kary GDPR mogą sięgać 20 milionów € lub 4% globalnego obrotu, a odszkodowania za naruszenie praw autorskich w USA wynosiły do 150 000 $ za pracę. Bezpieczniejsza postawa jest strukturalna: preferuj autoryzowane kanały ATS i pion SERP ofert pracy nad brutalnym forsowaniem tablic z zabezpieczeniami logowania, przechowuj pola faktograficzne (tytuł, firma, lokalizacja) zamiast ponownego publikowania pełnych opisów chronionych prawem autorskim i usuwaj dane osobowe, których nie potrzebujesz. Nasz przegląd legalności scrapingu w 2026 i saga zgodności z LinkedIn idą głębiej.

Panel statystyk pokazujący siedem platform ATS, 30-dniowe okno aktualności i karę 240 000 euro dla KASPR za scrapowanie LinkedIn
Ustrukturyzowane kanały ATS plus kanoniczna deduplikacja pokonują brutalny scraping HTML pod względem kosztów, pokrycia i narażenia prawnego.

Gdzie pasują proxy

Poziom ATS rzadko potrzebuje IP rezydencyjnych, ale crawl odkrywczy, pion SERP i każdy bezpośredni scraping tablic już tak — Google i większe tablice ograniczają szybkość według IP i różnicują wyniki geograficznie. Przekieruj je przez rotacyjne proxy rezydencyjne z rotacją na żądanie i geotargetowaniem, aby każde zapytanie miejskie pochodziło z odpowiadającej lokalizacji. Utrzymuj poziomy oddzielnie: tanie centrum danych dla łagodnego indeksu, rezydencyjne dla wrażliwych celów.

Często zadawane pytania

Czym jest agregator ofert pracy?

To wyszukiwarka ofert pracy, która zbiera oferty z wielu źródeł — stron karier firm, platform ATS, innych tablic i SERP ofert pracy — normalizuje je do jednego schematu, usuwa duplikaty i prezentuje je poszukującym pracy w jednym miejscu z możliwością wyszukiwania. Praca inżynieryjna polega na pozyskiwaniu, deduplikacji i aktualności, nie tylko na scrapingu.

Jak deduplikować oferty pracy z wielu źródeł?

Zbuduj klucz kanoniczny, normalizując i haszując tytuł pracy, firmę, lokalizację i zewnętrzny ID oferty źródła. Zamień na małe litery, usuń interpunkcję i zredukuj białe znaki najpierw, aby różne pisownie zredukowały się do jednego. Zachowaj pierwsze wystąpienie i usuń dopasowania. To wychwytuje tę samą rolę pojawiającą się na stronie pracodawcy, agregatorach i ofertach pracy Google.

Czy scraping tablic ofert pracy jest legalny?

To zależy od źródła, danych i twojej jurysdykcji. Publiczne pola faktograficzne ofert są mniej ryzykowne niż dane osobowe lub pełne opisy chronione prawem autorskim, a omijanie ścian logowania zwiększa narażenie w stylu CFAA. Autoryzowane kanały ATS i pion SERP ofert pracy to czystsze ścieżki. Firmy były surowo karane za scrapowanie danych osobowych — uzyskaj porady prawne dla komercyjnego użytku.

Jak świeże powinny być zebrane dane o ofertach pracy?

Ponownie pobieraj źródła o dużej objętości, takie jak kanały ATS, co godzinę, a długi ogon codziennie, następnie usuwaj każdą ofertę, której nie widziałeś ponownie w oknie przesuwnym — 30 dni to powszechna domyślna wartość. Śledź znacznik czasu ostatniego widzenia na ofertę i monitoruj objętość na źródło, aby złapać uszkodzone źródło, zanim użytkownicy zobaczą przestarzałe role.

Traktuj agregację jako trzy problemy — źródła, deduplikacja, aktualność — a scraping staje się szczegółem wspierającym. Prowadź z czystymi kanałami ATS i pionem SERP ofert pracy, deduplikuj na kluczu kanonicznym, agresywnie przycinaj i utrzymuj wrażliwe crawle na rotacyjnych IP rezydencyjnych. To różnica między produktem, któremu ludzie ufają, a cmentarzem martwych linków.

Zasil swój agregator za pomocą Scraper API