Jak zeskrobać dane z Glassdoor w Pythonie: oferty pracy, wynagrodzenia i opinie

Ostatnia aktualizacja: April 16, 2026
Jak zeskrobać dane z Glassdoor w Pythonie: oferty pracy, wynagrodzenia i opinie

Jeśli Twój zeskrobać Glassdoor w Pythonie działał świetnie w 2022 roku, a dziś zwraca już tylko błędy 403, nie jesteś sam. Na forach co chwilę pojawia się to samo pytanie: „Czy ktoś wie, dlaczego ten scraper już nie działa?”

Krótka odpowiedź: Glassdoor zmienił wszystko. Recruit Holdings połączył Glassdoor z Indeed w lipcu 2025 roku, zwolnił 1 300 pracowników i zaostrzył zabezpieczenia antybotowe do tego stopnia, że zwykłe skrypty oparte na Selenium i requests są blokowane, zanim wczyta się choćby pierwszy bajt HTML. Na luty 2026 logowanie do Glassdoor odbywa się już wyłącznie przez Indeed Login — więc każdy poradnik, który na sztywno zakłada formularz logowania charakterystyczny dla Glassdoor, jest od początku technicznie nieaktualny. Tymczasem platforma nadal gromadzi ponad 180 milionów łącznie opinii, danych o wynagrodzeniach i insightów dla 2,5 miliona pracodawców. To niezwykle cenny zasób dla benchmarków HR, analizy konkurencji i prospectingu sprzedażowego — o ile uda Ci się do niego dotrzeć. Ten przewodnik pokazuje wersję, która działa po wszystkich tych zmianach, i omawia trzy typy danych z Glassdoor (oferty pracy, opinie i wynagrodzenia) w jednym miejscu. Pokażę Ci podejście w Pythonie z działającym kodem z 2025 roku, wyjaśnię dokładnie, co Cię blokuje i jak to obejść, a także pokażę skrót bez kodowania dla osób, które wolą pominąć cały etap inżynierski.

Dlaczego warto zeskrobywać Glassdoor w Pythonie w 2025 roku?

Glassdoor to nie tylko portal z ofertami pracy. To jeden z najbogatszych w sieci zbiorów danych o pracodawcach — korzysta z niego około jedna trzecia firm z listy Fortune 500 i odwiedza go około 55 milionów unikalnych użytkowników miesięcznie. Dane ukryte za tymi stronami napędzają realne decyzje biznesowe w wielu zespołach.

Tak różne działy wykorzystują dane z Glassdoor:

Przypadek użyciaPotrzebny typ danychKto zyskuje
Benchmark wynagrodzeńRozkłady płac, liczba próbekHR, Total Rewards, Operations
Śledzenie rekrutacji konkurencjiOferty pracy, tempo publikacjiSales, Strategy, VC/Corp Dev
Monitorowanie marki pracodawcyTreść opinii, trendy ocen, akceptacja CEOHR, Marketing, Comms
Generowanie leadów (firmy w fazie wzrostu)Oferty pracy + informacje o firmieZespoły sprzedaży, SDR-y
Badania rynkowe / akademickieWszystkie trzyAnalitycy, konsultanci, badacze

glassdoor_stats_00937e478e.png

Gdy BLS nie mogło opublikować danych o zatrudnieniu podczas październikowego shutdownu rządu w 2025 roku, zespół Economic Research Glassdoor opublikował alternatywny raport o rynku pracy na podstawie własnego zbioru danych. To pokazuje, jak poważnie instytucjonalni analitycy traktują dziś te informacje.

Python nadal pozostaje pierwszym wyborem, bo ekosystem jest bezkonkurencyjny — Playwright do automatyzacji przeglądarki, parsel/lxml do parsowania, curl_cffi do obchodzenia fingerprintingu TLS oraz ogromna społeczność, która dzieli się działającymi wzorcami. Problem nie leży w Pythonie. Problem w tym, że Glassdoor stał się znacznie trudniejszy do zeskrobania.

Zeskrob dane z Glassdoor z pomocą AI Get Started Free

Jeśli szukasz rozwiązania bez kodowania do pobierania danych z Glassdoor, Thunderbit pomoże Ci zeskrobać oferty pracy, opinie i strony z wynagrodzeniami bez budowania i utrzymywania własnego stosu w Pythonie.

Jakie dane z Glassdoor da się w ogóle zeskrobać?

Większość poradników omawia tylko oferty pracy. Tymczasem największe zainteresowanie użytkowników — na podstawie wątków na forach, zgłoszeń na GitHubie i pytań na Reddicie, które śledziłem — dotyczy dwóch typów danych, których prawie nikt nie pokazuje: opinii i wynagrodzeń. Oto pełny podział tego, co da się wyciągnąć z każdej z trzech kategorii.

Oferty pracy

Najłatwiej dostępny typ danych. Możesz pobrać: stanowisko, nazwę firmy, lokalizację, szacowane wynagrodzenie, ocenę firmy, datę publikacji, oznaczenie easy apply i link do oferty. Część ofert jest dostępna bez logowania, choć po kilku stronach Glassdoor może wyświetlić popup logowania.

Opinie o firmach

Tu robi się naprawdę ciekawie z perspektywy analizy marki pracodawcy. Da się wyciągnąć: ocenę ogólną, oceny składowe (work-life balance, kultura i wartości, różnorodność i inkluzywność, możliwości rozwoju, wynagrodzenie i benefity, zarząd), sekcję zalet, sekcję wad, stanowisko autora opinii, datę opinii oraz status zatrudnienia. Pełna treść opinii jest za logowaniem — zobaczysz fragment, ale komplet zalet i wad wymaga autoryzacji.

Dane o wynagrodzeniach

Najczęściej poszukiwany i jednocześnie najbardziej frustrujący typ danych. Możesz pobrać: stanowisko, zakres płacy podstawowej, całkowity zakres wynagrodzenia, liczbę zgłoszeń płacowych i lokalizację. Jednak strony z wynagrodzeniami są w pełni chronione logowaniem, a Glassdoor czasem dokłada jeszcze flow „contribute to unlock”, w którym musisz podać własne wynagrodzenie, żeby zobaczyć cudze. Żaden konkurencyjny poradnik nie pokazuje na to działającego kodu — tutaj to naprawimy.

Co wymaga logowania, a co nie?

Ta tabela oszczędzi Ci odkrywania na własnej skórze, które strony zwrócą puste dane:

Typ danychDostępne bez logowania?Uwagi
Tytuły ofert pracy i podstawowe informacjeZazwyczaj takPo kilku stronach może pojawić się popup
Pełne opisy ofert pracyCzęściowoCzęsto blokowane po 2–3 podglądach
Opinie o firmach (pełny tekst)Nie — wymagane logowanieWidoczny jest fragment, pełny tekst jest zablokowany
Dane o wynagrodzeniachNie — wymagane logowanieMoże też pojawić się „contribute to unlock”

Dlaczego Twój stary scraper do Glassdoor jest najpewniej zepsuty

glassdoor_defense_82a26cd8bd.png

Powiem to wprost: jeśli kopiujesz kod z poradnika z lat 2021–2023, nie zadziała. Najpopularniejszy stary scraper Selenium do Glassdoor na GitHubie (MatthewChatham/glassdoor-review-scraper, ok. 1,4 tys. gwiazdek) ma ponad 12 otwartych, nierozwiązanych problemów — w tym „Glassdoor new UI design”, „Cloudflare anti-bot protection” i „NoSuchElementException”. Repozytorium jest w praktyce porzucone. Actor Apify glassdoor-jobs-scraper jest oznaczony jako DEPRECATED. ScrapeOps ocenia trudność scrapowania Glassdoor na 9/10 i trudność obejścia zabezpieczeń na 8/10.

Oto co się zmieniło i dlaczego stary kod przestaje działać:

Warstwa obronyCo się zmieniłoWpływ na stare scrapery
Cloudflare Bot ManagementOstrzejszy fingerprinting JA3/JA4 od 2024 rokuProste skrypty requests/Selenium dostają 403 niemal natychmiast
Dynamiczne nazwy klas CSSNazwy klas są losowane przy każdym buildzieStare selektory CSS z poradników przestają działać po cichu
Limity i śledzenie sesjiOstrzejsze limity per IP i per sesjaScrapery blokują się po mniejszej liczbie stron
CAPTCHA (prawdopodobnie Cloudflare Turnstile)Pojawia się częściej, zwłaszcza przy paginacjiHeadless browser uruchamia wyzwania
Szersza blokada logowaniaWięcej typów stron wymaga autoryzacjiStrony z wynagrodzeniami i opiniami zwracają puste dane
Migracja do Indeed Login (luty 2026)Formularz logowania Glassdoor został całkowicie zastąpionyKażdy kod celujący w stary DOM logowania jest martwy

Przewodnik Scrapfly z 2026 roku zawiera wyraźne ostrzeżenie: „Glassdoor is known for its high blocking rate, so if you get None values while running the Python code, it's likely you're getting blocked.” A wpis na DEV.to z marca 2026 mówi wprost: „Proste zapytania HTTP z requests lub httpx są blokowane natychmiast.”

Pokażę Ci środki zaradcze — Patchright (stealthowa odmiana Playwright), selektory oparte na atrybutach data-test, rotujące proxy residential i uwierzytelnione sesje trwałe — zaprojektowane dokładnie po to, by poradzić sobie z każdą z tych warstw.

Glassdoor API czy scraping w Pythonie: najpierw wybierz właściwe podejście

Na forach często pada pytanie: „Czy po prostu nie użyć Glassdoor API?” — odpowiedź brzmi: nie możesz.

Stare Glassdoor Partner API nie przyjmuje już nowych aplikacji. Portal dla deweloperów wciąż technicznie istnieje, ale zwraca HTTP 403. Nigdy nie istniał publiczny endpoint do opinii — scraper MatthewChatham powstał właśnie „dlatego, że Glassdoor nie ma API do opinii”. I nie ma też ścieżki migracji dla opinii ani wynagrodzeń przez Indeed Publisher API.

Oto uczciwe porównanie:

CzynnikGlassdoor Partner API v1Scraping w PythonieThunderbit (bez kodu)
DostępBrak nowych rejestracjiOtwarty (sam to implementujesz)Rozszerzenie Chrome
Oferty pracyOgraniczone / wygaszaneDostępne przy wysiłkuDostępne
Opinie o firmachPublicznie nigdy nie byłoTak (wymaga logowania)Tak (przez Browser Mode)
Dane o wynagrodzeniachPublicznie nigdy nie byłoTak (wymaga logowania)Tak
LimityNieudokumentowaneMasz kontrolę nad tempemOparte na kredytach
Nakład konfiguracjiNie da się zarejestrować nowych aplikacjiOd kilku godzin do kilku dniOkoło 2 minut
Koszt utrzymaniaBrak zastosowaniaWysoki (zmiany HTML psują kod)Niski (AI podpowiada pola ponownie)

Jeśli potrzebujesz opinii lub danych o wynagrodzeniach — a większość czytelników tego tekstu właśnie tego potrzebuje — scraping w Pythonie albo narzędzie no-code to jedyne realistyczne wyjście.

Zanim zaczniesz

  • Poziom trudności: Średniozaawansowany (warto dobrze znać Pythona i terminal)
  • Szacowany czas: ok. 30–60 minut na pełną konfigurację; potem ok. 10 minut na każdy typ danych
  • Czego potrzebujesz:
    • Python 3.10+ (zalecane 3.11 lub 3.12)
    • Zainstalowana przeglądarka Chrome
    • Konto Glassdoor (darmowe — potrzebne do danych o wynagrodzeniach i opinii)
    • Rotujące proxy residential (jeśli chcesz pobrać więcej niż kilka stron)
    • Opcjonalnie: Thunderbit Chrome Extension, jeśli chcesz ścieżkę bez kodu

Narzędzia i biblioteki do scrapowania Glassdoor w Pythonie w 2025 roku

Krajobraz narzędzi bardzo się zmienił. Oto, co naprawdę działa wobec aktualnych zabezpieczeń Glassdoor.

Dlaczego Patchright to najlepszy wybór do Glassdoor

Patchright to stealthowa odmiana Playwright, która łata wyciek Runtime.Enable w CDP — dokładnie ten techniczny powód, przez który zwykły Playwright przegrywa na stronach chronionych przez Cloudflare. Używa dokładnie tego samego API co Playwright, więc jeśli znasz Playwright, znasz też Patchright. Wersja 1.58.2 (marzec 2026) jest aktualna i aktywnie rozwijana.

W porównaniu z alternatywami:

  • Zwykły Playwright: jest wykrywany na stronie logowania Glassdoor z powodu wycieku Runtime.Enable
  • Selenium + undetected-chromedriver: ostatnie wydanie undetected-chromedriver było w lutym 2024 roku — to w praktyce rozwiązanie legacy. Benchmark Scrapfly pokazał, że „nie zadziałał na żadnej domenie w naszym teście”
  • requests + BeautifulSoup: nie renderują JavaScriptu i są blokowane od razu przez fingerprinting TLS Cloudflare
  • curl_cffi: świetne dla szybkiej ścieżki (10–20× szybciej niż przeglądarka), gdy strony dostarczają __NEXT_DATA__ w początkowym HTML, ale nie poradzi sobie z logowaniem ani ekranami pośrednimi

Biblioteki pomocnicze

  • parsel (1.11.0) lub lxml (6.0.4): szybkie parsowanie HTML/XPath
  • csv lub pandas: eksport danych
  • asyncio: asynchroniczne scrapowanie dla szybszej paginacji

Proxy: tylko residential

Warstwa Cloudflare w Glassdoor agresywnie wywołuje wyzwania dla ASN-ów datacenter. Proxy residential podobno obniżają współczynnik blokad z 20–30% do poniżej 5%. Ceny startowe to około $1,75/GB w IPRoyal (promocyjnie) albo $3,00/GB w Decodo. Przy scrapowaniu produkcyjnym warto założyć budżet $3–8/GB, zależnie od wolumenu.

Losowe opóźnienia między żądaniami (minimum 3–8 sekund, 5–15 sekund przy dłuższych przebiegach) są konieczne niezależnie od jakości proxy.

Krok 1: skonfiguruj środowisko Pythona

Utwórz folder projektu i zainstaluj zalecany zestaw:

mkdir glassdoor-scraper && cd glassdoor-scraper
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip

# Core stack
pip install patchright==1.58.2 parsel==1.11.0

# Install browser binaries
patchright install chromium

# Optional: fast path for __NEXT_DATA__ extraction
pip install "curl_cffi==0.15.0"

Powinieneś zobaczyć, jak Patchright pobiera binarkę Chromium. Jeśli patchright install chromium zakończy się błędem, sprawdź, czy masz wystarczająco dużo miejsca na dysku (ok. 300 MB) i czy używasz Pythona 3.10+.

Krok 2: uruchom Patchright i przejdź do Glassdoor

Oto bazowy wzorzec uruchomienia, który działa z warstwą Cloudflare Glassdoor:

from patchright.sync_api import sync_playwright
import random, time

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=False,          # headless nadal jest łatwiejszy do wykrycia
        channel="chrome",        # użyj prawdziwego Chrome, nie dołączonego Chromium
    )
    context = browser.new_context(
        viewport={"width": 1440, "height": 900},
        locale="en-US",
        timezone_id="America/New_York",
        user_agent=(
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/134.0.0.0 Safari/537.36"
        ),
    )
    page = context.new_page()
    page.goto(
        "https://www.glassdoor.com/Job/new-york-data-engineer-jobs-"
        "SRCH_IL.0,8_IC1132348_KO9,22.htm"
    )

    # Usuń nakładkę logowania — treść nadal jest w DOM
    page.add_style_tag(content="""
        #HardsellOverlay, .LoginModal { display: none !important; }
        body { overflow: auto !important; position: initial !important; }
    """)

    page.wait_for_selector("[data-test='jobListing']")
    print("Strona załadowana — oferty pracy są widoczne.")

Warto zwrócić uwagę na kilka rzeczy. Flaga channel="chrome" mówi Patchright, by używał zainstalowanego Chrome, a nie dołączonego Chromium — dzięki temu fingerprint przeglądarki jest bardziej wiarygodny. Trik z add_style_tag ukrywa modal logowania Glassdoor (nazywany #HardsellOverlay) bez klikania czegokolwiek. Scrapfly potwierdza, że „cała treść nadal tam jest, po prostu zasłonięta przez overlay” — HTML zawiera dane niezależnie od tego, czy modal jest widoczny.

Powinieneś zobaczyć okno Chrome, przejście na stronę wyszukiwania ofert w Glassdoor i wyświetlenie kart ofert bez blokującego popupu logowania.

Krok 3: zeskrob oferty pracy z Glassdoor

Zidentyfikuj stabilne selektory

Glassdoor losuje nazwy klas CSS przy każdym buildzie — więc selektor .jobCard_xyz123 z poradnika z 2023 roku dziś po prostu nic nie zwróci. Zamiast tego używaj atrybutów data-test, które są wewnętrzną konwencją QA Glassdoor i pozostają stabilne między wdrożeniami.

Oto zestawienie selektorów dla pól ofert pracy:

PoleSelektor
Kontener karty oferty[data-test="jobListing"]
Stanowisko[data-test="job-title"]
Link do ofertya[data-test="job-link"]
Nazwa firmy[data-test="employer-name"]
Lokalizacja[data-test="emp-location"]
Zakres wynagrodzenia[data-test="detailSalary"]
Ocena firmy[data-test="rating"]
Data publikacji[data-test="job-age"]
Następna strona paginacji[data-test="pagination-next"]

Pobierz dane o ofertach pracy

from parsel import Selector
import csv, random, time

def scrape_jobs(page, max_pages=5):
    all_jobs = []

    for page_num in range(1, max_pages + 1):
        html = page.content()
        sel = Selector(text=html)
        cards = sel.css('[data-test="jobListing"]')

        if not cards:
            print(f"Strona {page_num}: nie znaleziono kart — możliwa blokada albo zmiana selektora.")
            break

        for card in cards:
            job = {
                "title": card.css('[data-test="job-title"]::text').get("").strip(),
                "company": card.css('[data-test="employer-name"]::text').get("").strip(),
                "location": card.css('[data-test="emp-location"]::text').get("").strip(),
                "salary": card.css('[data-test="detailSalary"]::text').get("").strip(),
                "rating": card.css('[data-test="rating"]::text').get("").strip(),
                "link": card.css('a[data-test="job-link"]::attr(href)').get(""),
                "posted": card.css('[data-test="job-age"]::text').get("").strip(),
            }
            if job["link"] and not job["link"].startswith("http"):
                job["link"] = "https://www.glassdoor.com" + job["link"]
            all_jobs.append(job)

        print(f"Strona {page_num}: pobrano {len(cards)} ofert")

        # Paginacja
        next_btn = page.query_selector('[data-test="pagination-next"]')
        if next_btn and page_num < max_pages:
            next_btn.click()
            time.sleep(random.uniform(3, 8))
            page.wait_for_selector("[data-test='jobListing']")
        else:
            break

    return all_jobs

Zapisz do CSV

def save_to_csv(jobs, filename="glassdoor_jobs.csv"):
    if not jobs:
        print("Brak ofert do zapisania.")
        return
    keys = jobs[0].keys()
    with open(filename, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=keys)
        writer.writeheader()
        writer.writerows(jobs)
    print(f"Zapisano {len(jobs)} ofert do pliku {filename}")

Uwaga na limity paginacji: Glassdoor ogranicza wyniki wyszukiwania do około 30 stron niezależnie od łącznej liczby wyników. Jeśli potrzebujesz większego pokrycia, używaj filtrów (lokalizacja, typ pracy, zakres wynagrodzenia), aby zawęzić każde wyszukiwanie zamiast próbować przechodzić dalej niż limit.

W moich testach zeskrobanie 5 stron ofert pracy (około 75 ofert) zajęło około 45 sekund przy losowych opóźnieniach. Zrobienie tego ręcznie zajęłoby co najmniej 20 minut kopiowania i wklejania.

Krok 4: zeskrob opinie o firmach z Glassdoor

To sekcja, której żaden inny poradnik nie pokazuje z działającym kodem. Opinie są miejscem, gdzie kryje się prawdziwa inteligencja o pracodawcy — analiza sentymentu, sygnały kultury organizacyjnej, czerwone flagi dotyczące zarządzania.

Przejdź do strony opinii

Adresy opinii mają taki wzór: /Reviews/{Company}-Reviews-E{id}.htm. ID pracodawcy znajdziesz, wyszukując firmę w Glassdoor i sprawdzając URL.

def navigate_to_reviews(page, company_reviews_url):
    page.goto(company_reviews_url)
    page.add_style_tag(content="""
        #HardsellOverlay, .LoginModal { display: none !important; }
        body { overflow: auto !important; position: initial !important; }
    """)
    page.wait_for_selector('[data-test="review"]', timeout=15000)

Ukryty endpoint BFF (najczystsza ścieżka)

Oto najważniejsze odkrycie z moich badań: opinie Glassdoor mają działające wewnętrzne API JSON, które całkowicie omija parsowanie HTML. Repozytorium scraperów Scrapfly dokumentuje ten endpoint i jest on znacznie bardziej niezawodny niż scrapowanie DOM.

import json, re, requests

def get_review_ids(page):
    """Wyciąga employerId i dynamicProfileId z HTML strony opinii."""
    html = page.content()
    sel = Selector(text=html)
    script_text = sel.xpath(
        "//script[contains(text(), 'profileId')]/text()"
    ).get("")
    employer_match = re.search(r'"employer"\s*:\s*(\{[^}]+\})', script_text)
    if employer_match:
        meta = json.loads(employer_match.group(1))
        return meta.get("id"), meta.get("profileId")
    return None, None

def fetch_reviews_bff(page, employer_id, profile_id, max_pages=5):
    """Wywołuje wewnętrzny endpoint BFF Glassdoor i pobiera uporządkowane dane o opiniach."""
    all_reviews = []
    cookies = {c["name"]: c["value"] for c in page.context.cookies()}

    for pg in range(1, max_pages + 1):
        payload = {
            "applyDefaultCriteria": True,
            "employerId": employer_id,
            "dynamicProfileId": profile_id,
            "employmentStatuses": ["REGULAR", "PART_TIME"],
            "language": "eng",
            "onlyCurrentEmployees": False,
            "page": pg,
            "pageSize": 10,
            "sort": "DATE",
            "textSearch": "",
        }
        resp = requests.post(
            "https://www.glassdoor.com/bff/employer-profile-mono/employer-reviews",
            json=payload,
            cookies=cookies,
            headers={"Content-Type": "application/json"},
        )
        if resp.status_code != 200:
            print(f"BFF zwrócił {resp.status_code} na stronie {pg}")
            break

        data = resp.json()
        reviews = data.get("data", {}).get("employerReviews", {}).get("reviews", [])
        total_pages = data.get("data", {}).get("employerReviews", {}).get("numberOfPages", 1)

        for r in reviews:
            all_reviews.append({
                "title": r.get("summary", ""),
                "rating": r.get("ratingOverall"),
                "pros": r.get("pros", ""),
                "cons": r.get("cons", ""),
                "author_role": r.get("jobTitle", {}).get("text", ""),
                "date": r.get("reviewDateTime", ""),
                "recommend": r.get("isRecommend"),
            })

        print(f"Strona opinii {pg}/{total_pages}: pobrano {len(reviews)} opinii")
        if pg >= total_pages:
            break
        time.sleep(random.uniform(3, 6))

    return all_reviews

Endpoint BFF daje czysty JSON ze wszystkimi polami opinii — bez parsowania HTML i bez ryzyka, że selektory CSS się rozjadą. Potrzebujesz ciasteczek sesyjnych z uwierzytelnionego kontekstu Playwrighta (omówionego w kroku 6 poniżej) oraz musisz najpierw wyciągnąć employerId i dynamicProfileId z HTML strony opinii.

Zapasowe selektory HTML dla opinii

Jeśli endpoint BFF się zmieni albo wolisz parsowanie DOM, oto stabilne selektory data-test:

PoleSelektor
Kontener opinii[data-test="review"]
Nagłówek[data-test="review-title"]
Ocena ogólna[data-test="overall-rating"]
Zalety[data-test="pros"]
Wady[data-test="cons"]
Data[data-test="review-date"]
Stanowisko autora[data-test="author-jobTitle"]

Krok 5: zeskrob dane o wynagrodzeniach z Glassdoor

Strony z wynagrodzeniami są całkowicie chronione logowaniem. Musisz mieć uwierzytelnioną sesję (krok 6), zanim ten kod zwróci prawdziwe dane.

Przejdź do strony wynagrodzeń

Adresy wynagrodzeń mają wzór: /Salary/{Company}-Salaries-E{id}.htm, a paginacja wygląda jak _P{n}.htm.

def scrape_salaries(page, salary_url, max_pages=3):
    all_salaries = []

    for pg in range(1, max_pages + 1):
        url = salary_url if pg == 1 else salary_url.replace(".htm", f"_P{pg}.htm")
        page.goto(url)
        page.add_style_tag(content="""
            #HardsellOverlay { display: none !important; }
            body { overflow: auto !important; position: initial !important; }
        """)
        time.sleep(random.uniform(3, 7))

        html = page.content()
        sel = Selector(text=html)
        items = sel.css('[data-test="salary-item"]')

        if not items:
            print(f"Strona wynagrodzeń {pg}: brak pozycji — możliwa blokada logowania albo blokada antybotowa.")
            break

        for item in items:
            salary = {
                "job_title": item.css('[class*="SalaryItem_jobTitle__"]::text').get("").strip(),
                "salary_range": item.css('[class*="SalaryItem_salaryRange__"]::text').get("").strip(),
                "count": item.css('[class*="SalaryItem_salaryCount__"]::text').get("").strip(),
            }
            all_salaries.append(salary)

        print(f"Strona wynagrodzeń {pg}: pobrano {len(items)} wpisów")

    return all_salaries

Zwróć uwagę na wzorzec prefiksowy [class*="SalaryItem_jobTitle__"]. Strona wynagrodzeń Glassdoor używa klas CSS Module z haszowanymi nazwami (np. SalaryItem_jobTitle__XWGpT), gdzie końcowy hash zmienia się przy każdym wdrożeniu. Prefiks pozostaje stabilny — hash nie. Nigdy nie wpisuj na sztywno pełnej nazwy klasy.

Krok 6: przejdź przez blokadę logowania Glassdoor

To kluczowy element, który odblokowuje dane o wynagrodzeniach i pełny tekst opinii. Podejście jest takie: logujesz się raz ręcznie w widocznej przeglądarce, zapisujesz stan uwierzytelnionej sesji, a potem używasz go ponownie we wszystkich kolejnych uruchomieniach scrapera.

Zapisz uwierzytelnioną sesję

Uruchom ten skrypt raz. Otworzy on okno Chrome, przejdzie do strony logowania Glassdoor (która teraz przekierowuje do Indeed Login) i poczeka, aż zalogujesz się ręcznie:

import asyncio
from pathlib import Path
from patchright.async_api import async_playwright

STATE_FILE = Path("glassdoor_state.json")

async def login_and_save():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False, channel="chrome")
        context = await browser.new_context(
            viewport={"width": 1366, "height": 800},
            locale="en-US",
        )
        page = await context.new_page()
        await page.goto("https://www.glassdoor.com/profile/login_input.htm")
        print("Zaloguj się w oknie przeglądarki, a potem naciśnij Enter tutaj...")
        input()
        await context.storage_state(path=str(STATE_FILE))
        print(f"Sesja zapisana do pliku {STATE_FILE}")
        await browser.close()

asyncio.run(login_and_save())

Po zalogowaniu i naciśnięciu Enter Patchright zapisze wszystkie ciasteczka i local storage do glassdoor_state.json. Plik ten zawiera Twoje gdId, GSESSIONID, cf_clearance i tokeny uwierzytelniające.

Wykorzystaj zapisanej sesji do scrapowania

Każde kolejne uruchomienie scrapera wczytuje zapisany stan — bez ręcznego logowania:

async def scrape_with_auth(target_url):
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True, channel="chrome")
        context = await browser.new_context(
            storage_state="glassdoor_state.json"
        )
        page = await context.new_page()
        await page.goto(target_url)
        await page.add_style_tag(
            content="#HardsellOverlay{display:none!important}"
        )
        await page.wait_for_load_state("networkidle")
        html = await page.content()
        await browser.close()
        return html

Zapisana sesja zwykle działa przez 20–30 minut aktywnego użycia, zanim Glassdoor ponownie rzuci wyzwanie. Przy dłuższych przebiegach dodaj prosty test: jeśli z strony, która powinna zawierać dane, dostaniesz zero wyników, uruchom ponownie skrypt logowania, aby odświeżyć plik stanu.

Jak wykrywać i zamykać popup logowania

Dla częściowo zablokowanych stron (oferty pracy, które pokazują dane, ale nakładają modal), działa opisane wcześniej wstrzyknięcie CSS:

page.add_style_tag(content="""
    #HardsellOverlay, .LoginModal { display: none !important; }
    body { overflow: auto !important; position: initial !important; }
""")

Działa to tylko wtedy, gdy HTML pod nakładką już zawiera dane. W przypadku stron całkowicie blokowanych po stronie serwera (wynagrodzenia, głębsze strony opinii) jedyną drogą jest uwierzytelniona sesja z kroku 6.

Wskazówki, jak utrzymać scraper do Glassdoor przy życiu

Glassdoor często aktualizuje frontend. Oto jak zwiększyć odporność scrapera.

Preferuj atrybuty data-test zamiast nazw klas

Glassdoor losuje nazwy klas CSS, ale zwykle utrzymuje stabilne atrybuty data-test. Zawsze wybieraj [data-test="jobListing"] zamiast .jobCard_abc123. Gdy data-test nie jest dostępny (jak przy polach płacowych), użyj wzorca prefiksowego: [class*="SalaryItem_jobTitle__"].

Rotuj proxy i losuj opóźnienia

Używaj rotujących proxy residential — IP z centrów danych są sprawdzane niemal od razu. Dodaj losowe opóźnienia 3–8 sekund między ładowaniami stron (5–15 sekund przy dłuższych przebiegach). Jeśli to możliwe, unikaj scrapowania w godzinach pracy w USA, gdy wykrywanie behawioralne Cloudflare jest najostrzejsze.

Monitoruj, czy coś się nie zepsuło

Dodaj do scrapera prosty test: jeśli strona, która powinna zawierać dane, zwraca zero rekordów, traktuj to jako problem z selektorem, a nie jako pusty wynik, i wyślij alert. Uruchamiaj mały testowy scraping raz w tygodniu, aby szybko wyłapać awarie — Glassdoor wdraża zmiany frontendu bez zapowiedzi.

Używaj szybkiej ścieżki __NEXT_DATA__, gdy tylko to możliwe

Glassdoor to aplikacja Next.js + Apollo GraphQL. Wiele stron dostarcza tag <script id="__NEXT_DATA__">, który zawiera pełny cache GraphQL jako JSON. Parsowanie tego jest znacznie odporniejsze niż scrapowanie DOM i całkowicie omija overlay Hardsell:

import json

def extract_next_data(html):
    sel = Selector(text=html)
    raw = sel.css("script#__NEXT_DATA__::text").get()
    if raw:
        return json.loads(raw)["props"]["pageProps"].get("apolloCache", {})
    return None

Zwraca to uporządkowany cache Apollo ze wszystkimi polami ofert, opinii i wynagrodzeń — bez potrzeby używania selektorów CSS. To najbardziej odporna strategia ekstrakcji, jaką masz do dyspozycji, bo korzysta z tych samych danych, które napędzają frontend React Glassdoor.

Pomiń kod: zeskrob Glassdoor z Thunderbit (bez Pythona)

Nie każdy czytelnik jest programistą. Zespoły HR, rekruterzy, analitycy sales ops i badacze rynku też potrzebują danych z Glassdoor — i nie powinni mieć zarządzać kontekstami Playwrighta oraz rotacją proxy.

Thunderbit to rozszerzenie Chrome typu AI Web Scraper, które potrafi wyciągnąć te same dane o ofertach pracy, opiniach i wynagrodzeniach bez pisania ani jednej linijki kodu. Pracuję w zespole Thunderbit, więc mówię to otwarcie — ale powód, dla którego umieszczam je tutaj, jest prosty: naprawdę rozwiązuje dwa najtrudniejsze problemy w scrapowaniu Glassdoor.

Jak Thunderbit działa na Glassdoor

Proces zajmuje dwa kliknięcia:

  1. Otwórz dowolną stronę Glassdoor w Chrome (wyszukiwanie ofert, opinie o firmie, strona wynagrodzeń)
  2. Kliknij AI Suggest Fields w bocznym panelu Thunderbit — AI odczyta DOM strony i zaproponuje kolumny (stanowisko, firma, ocena, zakres płacy, zalety, wady itd.)
  3. Kliknij Scrape — dane zostaną wyciągnięte do tabeli bez selektorów CSS i bez kodu automatyzującego przeglądarkę

Thunderbit ma gotowy szablon do scrapowania firm z Glassdoor, który wyciąga ponad 23 pola dla jednej firmy w jednym przebiegu. W przypadku ofert pracy, opinii lub wynagrodzeń uniwersalny workflow AI Suggest Fields obsłuży dowolny URL z Glassdoor.

Jak obejść blokadę logowania bez kodu

To właśnie przewaga Thunderbit w przypadku Glassdoor. Browser Mode działa w Twojej własnej sesji Chrome — jeśli jesteś zalogowany do Glassdoor w Chrome, Thunderbit automatycznie dziedziczy te ciasteczka. Blokada logowania przy wynagrodzeniach i opiniach, która zatrzymuje serwerowe scrapery, po prostu przestaje mieć znaczenie. Bez zarządzania cookies, bez trwałych kontekstów, bez kodu sesji.

Scrapowanie podstron dla wzbogacenia danych

Zacznij od strony listy (np. 30 firm z wyników wyszukiwania), pozwól Thunderbit wyliczyć wiersze, a następnie włącz subpage scraping, aby odwiedzić stronę opinii lub wynagrodzeń każdej firmy i wzbogacić tabelę o pełne opisy, tekst opinii lub dane płacowe.

Eksport do narzędzi biznesowych

W przeciwieństwie do skryptów Pythona, które zapisują CSV lub JSON, Thunderbit eksportuje bezpośrednio do Google Sheets, Airtable, Notion lub Excela — za darmo w każdym planie. To szczególnie przydatne dla zespołów, które muszą wspólnie analizować dane.

Python czy Thunderbit: kiedy wybrać co?

ScenariuszRekomendowane podejście
Budujesz cykliczny pipeline danychPython + Patchright
Jednorazowe badanie lub mały projekt zespołowyThunderbit
Potrzebujesz programowej kontroli nad każdym polemPython
Nie jesteś programistą i potrzebujesz danych z Glassdoor już dziśThunderbit
Scrapowanie 1 000+ stron w jednym przebieguPython + proxy
Scrapowanie 30 firm z wzbogaceniem danychOba działają — Thunderbit jest szybszy w konfiguracji

Cennik Thunderbit zaczyna się od planu darmowego (6 stron/miesiąc), a plan Pro kosztuje 38 USD/miesiąc i obejmuje 3 000 kredytów. Przy 1 kredycie za każdy wiersz wynikowy (2 kredyty za scrapowanie podstron) wystarczy to mniej więcej na 33 przebiegi po 30 wzbogaconych firm miesięcznie.

Wypróbuj Thunderbit do scrapowania Glassdoor

Czy scrapowanie Glassdoor jest legalne?

Będę krótki i konkretny. Regulamin Glassdoor wyraźnie zakazuje automatycznego scrapowania: „You may not use any robot, spider, scraper... to access the Services for any purpose without our express written permission.”

Sytuacja prawna jest jednak bardziej złożona niż jeden zapis w ToS:

  • Meta v. Bright Data (N.D. Cal., styczeń 2024): sąd uznał, że jeśli nigdy się nie logujesz, to nigdy nie zaakceptowałeś ToS, a publiczne scrapowanie bez logowania nie narusza tych warunków
  • hiQ Labs v. LinkedIn (9th Cir.): CFAA nie ma zastosowania do automatycznego pobierania publicznie dostępnych danych — ale fałszywe konta i scrapowanie po zalogowaniu to już inna historia
  • Van Buren v. United States (Sąd Najwyższy, 2021): zawęził pojęcie „exceeds authorized access” w CFAA

Praktyczny wniosek: scrapowanie publicznych ofert pracy bez logowania znajduje się względnie po bezpieczniejszej stronie prawa. Scrapowanie po zalogowaniu oznacza, że zaakceptowałeś regulamin przy rejestracji, a on wprost tego zabrania. Dotyczy to tak samo skryptów Pythona, jak i Browser Mode w Thunderbit.

Warto przestrzegać zasad etycznych niezależnie od wszystkiego:

  • ustawiaj limity znacznie poniżej ludzkiego tempa przeglądania
  • nie pobieraj ani nie odsprzedawaj danych osobowych recenzentów
  • respektuj wytyczne robots.txt
  • pobieraj tylko te pola, których naprawdę potrzebujesz

Wnioski: która metoda będzie najlepsza dla Ciebie?

Ten przewodnik omówił wszystkie trzy typy danych z Glassdoor — oferty pracy, opinie i wynagrodzenia — pokazując działający kod na 2025 rok, uwzględniający migrację do Indeed Login, Cloudflare Bot Management oraz rotację nazw klas CSS Module, która zepsuła wszystkie starsze poradniki.

Oto rama decyzyjna:

Twoja sytuacjaNajlepsza ścieżka
Programista budujący pipeline danychPython + Patchright (postępuj według instrukcji krok po kroku powyżej)
Jednorazowe badanie lub małe, cykliczne pobraniaThunderbit (bez kodu, w przeglądarce)
Potrzebujesz tylko podstawowych ofert pracy na małą skalęNajpierw sprawdź, czy dostęp do Glassdoor API jest jeszcze możliwy (prawdopodobnie nie)
Potrzebujesz konkretnie danych o wynagrodzeniach lub opiniachMusisz użyć scrapingu w Pythonie albo Thunderbit — API nigdy tego nie obejmowało
Zespół osób nietechnicznych, który potrzebuje wspólnych danychThunderbit → eksport do Google Sheets

Zabezpieczenia Glassdoor będą się dalej zmieniać. Selektory będą się psuły. Pojawią się nowe wyzwania. Dodaj ten przewodnik do zakładek — a jeśli chcesz głębiej poznać narzędzia i techniki web scrapingu, sprawdź nasze wpisy o najlepszych automatycznych narzędziach do web scrapingu, jak zeskrobać dane ze strony internetowej w Pythonie oraz najlepszych narzędziach do scrapowania ofert pracy. Możesz też obejrzeć omówienia na Thunderbit YouTube Channel.

Wypróbuj Thunderbit do pobierania danych z Glassdoor Get Started Free

FAQ

1. Czy da się zeskrobać Glassdoor bez logowania?

Tak, w przypadku większości danych z ofert pracy i podstawowych ocen firmy. Nie, jeśli chodzi o pełne zestawienia wynagrodzeń albo pełny tekst opinii poza pierwszymi stronami. #HardsellOverlay to modal tylko w CSS — pod spodem HTML nadal zawiera dane z pierwszej strony — ale głębsza treść jest po stronie serwera chroniona przez blokadę „give-to-get”.

2. Jaka biblioteka Pythona najlepiej sprawdza się do scrapowania Glassdoor w 2025 roku?

Patchright (stealthowa odmiana Playwright) to domyślna rekomendacja. Łata wyciek Runtime.Enable w CDP, który ma zwykły Playwright i który Cloudflare wyraźnie sprawdza. Dla stron ofert, które dostarczają __NEXT_DATA__ w początkowym HTML, curl_cffi z impersonate="chrome124" jest 10–20× szybsze, ale nie obsłuży stron za logowaniem.

3. Jak uniknąć blokady podczas scrapowania Glassdoor?

Używaj Patchright albo rebrowser-playwright (nie zwykłego Playwrighta ani Selenium). Rotuj proxy residential — IP z datacenter są wyzwalane od razu. Dodawaj losowe opóźnienia 3–8 sekund między stronami. Zachowuj ciasteczka (gdId, cf_clearance, GSESSIONID) między żądaniami. Zakładaj okno sesji 20–30 minut przed ponownym wyzwaniem.

4. Czy istnieje API Glassdoor, którego mogę użyć zamiast scrapingu?

W praktyce nie. Stare Partner API nie przyjmuje już nowych aplikacji, publiczny endpoint do opinii nigdy nie istniał, a przez Indeed Publisher API nie ma ścieżki migracji. Scraping albo narzędzie no-code, takie jak Thunderbit, to jedyne praktyczne rozwiązanie dla opinii i danych o wynagrodzeniach.

5. Jak często scrapery do Glassdoor przestają działać?

Bardzo często. Glassdoor wdraża zmiany frontendu bez zapowiedzi, a hasze nazw klas CSS Module zmieniają się przy każdym buildzie. Najstabilniejsze strategie ekstrakcji to: (1) selektory atrybutów data-test, (2) blob JSON __NEXT_DATA__, oraz (3) wewnętrzny endpoint BFF dla opinii. Dodaj kontrolę zero wyników i uruchamiaj mały testowy scraping co tydzień, aby wcześnie wykrywać awarie.

Dowiedz się więcej

Ke
Ke
CTO w Thunderbit | Starszy data scientist i ekspert ML Dzięki prawie dziesięciu latom doświadczenia w uczeniu maszynowym i data science, Ke Shen jest absolwentem Columbia University i byłym starszym data scientistą w Walmart Labs. Dysponując dogłębną, uznaną przez branżowych ekspertów wiedzą w zakresie Python, R, Java i statystyki, dzieli się sprawdzonymi w boju spostrzeżeniami na temat wdrażania złożonych algorytmów AI — od teorii po architekturę gotową do produkcji.
Spis treści

Zbierz dane ze strony, po prostu o to prosząc

Powiedz, czego potrzebujesz, prostym angielskim. A najlepiej: nie mów nic.

Wypróbuj Thunderbit darmowe
Wyodrębniaj dane dzięki AI
Łatwo przenoś dane do Google Sheets, Airtable lub Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week