Glassdoorin kaapiminen Pythonilla: työpaikat, palkat ja arviot

Viimeksi päivitetty April 16, 2026
Glassdoorin kaapiminen Pythonilla: työpaikat, palkat ja arviot

Jos Glassdoor-kaapimesi toimi mainiosti vuonna 2022 ja antaa nyt pelkkiä 403-virheitä, et todellakaan ole ainoa. Foorumit toisensa jälkeen täyttyvät samasta kysymyksestä: "Tietääkö kukaan, miksi tämä kaavin ei enää toimi?"

Lyhyt vastaus: Glassdoor muutti kaiken. Recruit Holdings sulautti Glassdoorin Indeediin heinäkuussa 2025, vähensi 1 300 työntekijää ja kiristi bottisuojausta siihen pisteeseen, että perinteiset Selenium- ja requests-pohjaiset kaapimet estetään jo ennen kuin ensimmäistäkään HTML-bittiä ehditään ladata. Helmikuusta 2026 lähtien Glassdoor-kirjautuminen hoidetaan täysin Indeed Login -palvelun kautta — joten kaikki oppaat, joissa Glassdoorin oma kirjautumislomake on koodattu suoraan mukaan, ovat jo valmiiksi rikki. Samaan aikaan palvelussa on yhä yli 180 miljoonaa arvostelua, palkkatietoa ja muuta dataa yli 2,5 miljoonalta työnantajalta. Tuo data on todella arvokasta HR-vertailuun, kilpailija-analyysiin ja myynnin prospektointiin — jos siihen vain pääsee käsiksi. Tämä opas on juuri se versio, joka toimii kaikkien näiden muutosten jälkeen, ja se kattaa kaikki kolme Glassdoorin datatyyppiä (työpaikat, arviot JA palkat) yhdessä paikassa. Käyn läpi Python-lähestymistavan toimivalla vuoden 2025 koodilla, selitän tarkasti, mikä estää pääsyn ja miten sen voi kiertää, sekä näytän myös no-code-oikotien niille, jotka haluavat ohittaa koko teknisen puolen.

Miksi Glassdoor kannattaa kaapia Pythonilla vuonna 2025?

Glassdoor ei ole vain työpaikkasivusto. Se on yksi verkon rikkaimmista työnantajadataseteistä — lähde, jota käyttää noin kolmasosa Fortune 500 -yrityksistä, ja jolla on noin 55 miljoonaa kuukausittaista yksittäistä kävijää. Näiden sivujen taustalla oleva data ohjaa oikeita liiketoimintapäätöksiä useissa tiimeissä.

Näin eri tiimit hyödyntävät Glassdoor-dataa käytännössä:

KäyttötapausTarvittava datatyyppiHyötyjät
Palkkojen vertailuPalkkajakaumat, otoskootHR, Total Rewards, operatiiviset tiimit
Kilpailijoiden rekrytoinnin seurantaTyöpaikkailmoitukset, julkaisutahtiMyynti, strategia, VC/yritysostotiimit
Työnantajabrändin seurantaArvosteluteksti, arvioiden trendit, toimitusjohtajan hyväksyntäHR, markkinointi, viestintä
Liidien generointi (kasvuyritykset)Työpaikat + yritystiedotMyyntitiimit, SDR:t
Markkina- tai akateeminen tutkimusKaikki kolmeAnalyytikot, konsultit, tutkijat

glassdoor_stats_00937e478e.png

Kun BLS ei pystynyt julkaisemaan työmarkkinadataa lokakuun 2025 hallinnon sulun aikana, Glassdoorin oma Economic Research -tiimi julkaisi vaihtoehtoisen työpaikkaraportin omasta datastaan. Näin vakavasti tämän aineiston merkitys nykyään otetaan myös institutionaalisessa analytiikassa.

Python on edelleen luonnollinen valinta, koska sen ekosysteemi on vaikea päihittää — Playwright selainten automatisointiin, parsel/lxml jäsentämiseen, curl_cffi TLS-sormenjäljen kiertämiseen sekä laaja yhteisö, joka jakaa toimivia käytäntöjä. Ongelma ei ole Python. Ongelma on se, että Glassdoorista tuli paljon vaikeampi kaivaa dataa.

Kaavi Glassdoor-dataa tekoälyllä Get Started Free

Jos haluat no-code-varavaihtoehdon Glassdoor-datan poimintaan, Thunderbitin avulla voit kaivaa työpaikat, arviot ja palkkasivut ilman oman Python-pinon rakentamista ja ylläpitoa.

Mitä Glassdoor-dataa voit oikeasti kaivaa?

Useimmat oppaat käsittelevät vain työpaikkailmoituksia. Mutta käyttäjien kysyntä — foorumiketjujen, GitHub-issueiden ja seuraamieni Reddit-kysymysten perusteella — on suurin juuri kahdessa tietotyypissä, joita kukaan ei kunnolla opeta: arvioissa ja palkoissa. Tässä on koko kuva kaikesta, mitä näistä kolmesta kategoriasta voi poimia.

Työpaikkailmoitukset

Helpoin datatyyppi. Voit poimia: työnimike, yrityksen nimi, sijainti, palkka-arvio, yrityksen arvosana, julkaisupäivä, easy apply -merkintä ja työpaikkalinkki. Työpaikkailmoitukset ovat osittain nähtävissä ilman kirjautumista, vaikka Glassdoor voi näyttää kirjautumisponnahdusikkunan muutaman sivun jälkeen.

Yritysarviot

Tässä mennään työnantajabrändin analyysin kannalta kiinnostavalle alueelle. Poimittavia kenttiä ovat: kokonaisarvosana, osa-arviot (työ- ja vapaa-ajan tasapaino, kulttuuri ja arvot, monimuotoisuus ja osallisuus, uramahdollisuudet, palkka ja edut, ylin johto), plussat-teksti, miinukset-teksti, arvion kirjoittajan työnimike, arviointipäivä ja työsuhteen tila. Koko arvosteluteksti on kirjautumisen takana — näet katkelman, mutta täysi plussa/miinus-teksti vaatii tunnistautumisen.

Palkkatiedot

Eniten pyydetty ja samalla turhauttavin datatyyppi. Voit poimia: työnimike, peruspalkkahaarukka, kokonaiskorvauksen haarukka, palkkaraporttien määrä ja sijainti. Palkkasivut ovat kuitenkin kokonaan kirjautumisen takana, ja Glassdoor lisää joskus vielä "contribute to unlock" -vaiheen, jossa sinun pitää lisätä oma palkkasi ennen kuin näet muiden tiedot. Yksikään kilpailijaopas ei tarjoa tähän toimivaa koodia — korjataan se tässä.

Mitä voi nähdä ilman kirjautumista ja mikä vaatii sen?

Tämä taulukko säästää sinut siltä, että huomaat vasta liian myöhään, mitkä sivut palauttavat tyhjää dataa:

DatatyyppiSaatavilla ilman kirjautumista?Huomioitavaa
Työpaikkailmoituksen otsikko ja perustiedotUseimmiten kylläPonnahdusikkuna voi ilmestyä muutaman sivun jälkeen
Täysi työnkuvausOsittainUsein lukittu 2–3 katselun jälkeen
Yritysarviot (täysi teksti)Ei — kirjautuminen vaaditaanKatkelma näkyy, koko teksti on lukittu
PalkkatiedotEi — kirjautuminen vaaditaanSaattaa vaatia myös "contribute to unlock" -toiminnon

Miksi vanha Glassdoor-kaavimesi on todennäköisesti rikki

glassdoor_defense_82a26cd8bd.png

Sanon tämän suoraan: jos kopioit koodia vuoden 2021–2023 oppaasta, se ei tule toimimaan. GitHubin eniten tähdityllä vanhalla Glassdoor Selenium -kaapimella (MatthewChatham/glassdoor-review-scraper, noin 1,4k tähteä) on yli 12 avointa, ratkomatonta issuea — muun muassa "Glassdoor new UI design", "Cloudflare anti-bot protection" ja "NoSuchElementException". Repositorio on käytännössä hylätty. Apifyn glassdoor-jobs-scraper-actor on merkitty DEPRECATED. ScrapeOps antaa Glassdoorille kokonaisvaikeudeksi 9/10 ja ohitusvaikeudeksi 8/10.

Tässä on, mikä muuttui ja miksi vanha koodi hajoaa:

SuojauskerrosMikä muuttuiVaikutus vanhoihin kaapimiin
Cloudflare Bot ManagementTiukempi JA3/JA4-sormenjäljen tarkistus vuodesta 2024 alkaenPerus requests/Selenium-skriptit saavat 403-virheen heti
Dynaamiset CSS-luokatLuokkien nimet satunnaistetaan jokaisessa buildissaOppaista kopioidut vanhat CSS-selectorit lakkaavat toimimasta hiljaa
Nopeusrajoitukset + sessioseurantaTiukemmat rajoitukset IP-osoitetta ja sessiota kohtiKaapimet blokataan jo aikaisemman sivumäärän jälkeen
CAPTCHA-haasteet (todennäköisesti Cloudflare Turnstile)Yleistyvät, erityisesti sivutuksessaHeadless-selaimet laukaisevat haasteet
Laajennettu kirjautumismuuriYhä useammat sivutyypit vaativat tunnistautumisenPalkka- ja arviointisivut palauttavat tyhjää dataa
Indeed Login -siirtymä (helmi 2026)Glassdoorin kirjautumislomake korvattiin kokonaanKaikki koodi, joka kohdistuu vanhaan kirjautumis-DOMiin, on kuollut

Scrapflyn vuoden 2026 opas sisältää suoran varoituksen: "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." Ja DEV.to-kirjoitus maaliskuulta 2026 sanoo tämän vielä suoremmin: "Simple HTTP requests with requests or httpx get blocked instantly."

Vastatoimet, jotka näytän tässä — Patchright (stealth Playwright -haara), data-test-attribuuttiselektorit, kiertävät residential-proxyt ja autentikoidut pysyvät sessiot — on rakennettu juuri näiden suojakerrosten käsittelyyn.

Glassdoor API vai Python-kaappaus: valitse oikea lähestymistapa ensin

Monissa keskusteluketjuissa kysytään: "Pitäisikö minun vain käyttää Glassdoor APIa?" — ja vastaus on: et voi.

Vanha Glassdoor Partner API on suljettu uusilta hakijoilta. Kehittäjäportaali on teknisesti yhä olemassa, mutta palauttaa HTTP 403 -virheen. Julkista reviews-endpointia ei koskaan ollutkaan — MatthewChathamin kaavin tehtiin juuri siksi, että "Glassdoorilla ei ole APIa arvioille." Eikä Indeedin Publisher API tarjoa migraatiopolkua arvioille tai palkkatiedoille.

Tässä rehellinen vertailu:

TekijäGlassdoor Partner API v1Python-kaappausThunderbit (no-code)
KäyttöoikeusSuljettu uusilta hakijoiltaAvoin (itse toteutettava)Chrome-laajennus
TyöpaikkailmoituksetRajoitetusti / poistumassaSaatavilla vaivallaSaatavilla
YritysarviotEi koskaan ollut julkisesti tarjollaKyllä (kirjautuminen vaaditaan)Kyllä (Browser Mode)
PalkkatiedotEi koskaan ollut julkisesti tarjollaKyllä (kirjautuminen vaaditaan)Kyllä
NopeusrajatEi dokumentoituSinä hallitset tahdinCredit-pohjainen
Käyttöönoton vaivaUusia appeja ei voi rekisteröidäTunteja tai päiviäNoin 2 minuuttia
YlläpitotaakkaEi sovelluKorkea (HTML-muutokset rikkovat koodin)Matala (tekoäly ehdottaa kentät uudelleen)

Jos tarvitset arvioita tai palkkatietoja — ja useimmat tätä lukeva tarvitsevat — Python-kaappaus tai no-code-työkalu on ainoa realistinen vaihtoehto.

Ennen kuin aloitat

  • Vaikeustaso: Keskitaso (sinun kannattaa hallita Python ja terminaali)
  • Aika: Noin 30–60 minuuttia koko käyttöönottoon; sen jälkeen noin 10 minuuttia per datatyyppi
  • Tarvitset:
    • Python 3.10+ (suositus 3.11 tai 3.12)
    • Chrome-selain asennettuna
    • Glassdoor-tili (ilmainen — tarvitaan palkka- ja arviointitietoja varten)
    • Kiertävät residential-proxyt (jos kaivat enemmän kuin kourallisen sivuja)
    • Valinnainen: Thunderbit Chrome -laajennus, jos haluat no-code-polun

Työkalut ja kirjastot Glassdoorin kaapimiseen Pythonilla vuonna 2025

Työkalutilanne on muuttunut rajusti. Tässä on se, mikä oikeasti toimii Glassdoorin nykyisiä suojauksia vastaan.

Miksi Patchright on paras valinta Glassdoorille

Patchright on Playwrightin stealth-haara, joka paikkaa Runtime.Enable CDP -vuodon — juuri sen teknisen syyn, miksi vakio-Playwright kaatuu Cloudflare-suojatuilla sivustoilla. Se käyttää täsmälleen samaa APIa kuin Playwright, joten jos osaat Playwrightin, osaat Patchrightin. Versio 1.58.2 (maaliskuu 2026) on ajantasainen ja aktiivisesti ylläpidetty.

Vaihtoehtoihin verrattuna:

  • Vakioversion Playwright: Glassdoorin kirjautumissivu havaitsee sen Runtime.Enable-vuodon takia
  • Selenium + undetected-chromedriver: undetected-chromedriverin viimeinen julkaisu oli helmikuussa 2024 — se on käytännössä vanhaa teknologiaa. Scrapflyn benchmark totesi, että se "failed on every domain in our test"
  • requests + BeautifulSoup: Ei pysty renderöimään JavaScriptiä, ja Cloudflaren TLS-sormenjälki blokkaa sen heti
  • curl_cffi: Erinomainen nopeaan polkuun (10–20x nopeampi kuin selain), kun sivut toimittavat __NEXT_DATA__-tiedon alkuperäisessä HTML:ssä, mutta ei pysty käsittelemään kirjautumista tai välikyselyitä

Tukikirjastot

  • parsel (1.11.0) tai lxml (6.0.4): Nopea HTML/XPath-jäsentäminen
  • csv tai pandas: Datan vienti
  • asyncio: Asynkroninen kaappaus nopeampaan sivutukseen

Proxyt: vain residential-proxyt

Glassdoorin Cloudflare-kerros haastaa datakeskus-ASN:t aggressiivisesti. Residential-proxyt laskevat raportoidusti estojen määrän 20–30 prosentista alle 5 prosenttiin. Aloitushinnat ovat noin $1.75/GB IPRoyalilta (kampanja) tai $3.00/GB Decodolta. Tuotantokaappauksessa kannattaa varata $3–8/GB volyymista riippuen.

Satunnaiset viiveet pyyntöjen välillä (vähintään 3–8 sekuntia, pidemmissä ajoissa 5–15 sekuntia) ovat välttämättömiä proxyn laadusta riippumatta.

Vaihe 1: Aseta Python-ympäristö kuntoon

Luo projektikansio ja asenna suositeltu pino:

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"

Sinun pitäisi nähdä, että Patchright lataa Chromium-binaarin. Jos patchright install chromium epäonnistuu, varmista, että levytilaa on riittävästi (noin 300 Mt) ja että Python-versiosi on 3.10+.

Vaihe 2: Käynnistä Patchright ja siirry Glassdooriin

Tässä on peruskäynnistys, joka toimii Glassdoorin Cloudflare-kerrosta vastaan:

from patchright.sync_api import sync_playwright
import random, time

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=False,          # headless on yhä helpommin havaittavissa
        channel="chrome",        # käytä oikeaa Chromea, älä paketoitua Chromiumia
    )
    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"
    )

    # Poista kirjautumispeite — sisältö on silti DOMissa
    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("Sivu latautui — työpaikkailmoitukset näkyvät.")

Muutama huomio. channel="chrome"-valitsin ohjaa Patchrightin käyttämään asennettua Chromea sen oman Chromiumin sijaan — tämä tuottaa aidomman selainjäljityksen. add_style_tag-temppu piilottaa Glassdoorin kirjautumismodaalin (#HardsellOverlay) ilman että mitään tarvitsee klikata. Scrapfly vahvistaa, että "all of the content is still there, it's just covered up by the overlay" — HTML sisältää datan riippumatta siitä, näkyykö modaali vai ei.

Sinun pitäisi nähdä Chrome-ikkunan avautuvan, Glassdoorin työpaikkahakusivun latautuvan ja työpaikkakorttien näkyvän ilman kirjautumisponnahdusikkunaa.

Vaihe 3: Kaavi Glassdoorin työpaikkailmoitukset

Tunnista vakaat selektorit

Glassdoor satunnaistaa CSS-luokkien nimet jokaisessa buildissa — joten vuoden 2023 opetusohjelmasta kopioitu .jobCard_xyz123-selektori palauttaa nykyään hiljaisesti tyhjää. Käytä sen sijaan data-test-attribuutteja, jotka ovat Glassdoorin sisäinen QA-käytäntö ja pysyvät vakaina julkaisujen välillä.

Tässä on työpaikkailmoitusten kenttien selektoriviite:

KenttäSelektori
Työpaikkakortin kontti[data-test="jobListing"]
Työnimike[data-test="job-title"]
Työpaikkalinkkia[data-test="job-link"]
Yrityksen nimi[data-test="employer-name"]
Sijainti[data-test="emp-location"]
Palkkahaarukka[data-test="detailSalary"]
Yrityksen arvosana[data-test="rating"]
Julkaisupäivä[data-test="job-age"]
Seuraava sivu[data-test="pagination-next"]

Poimi työpaikkadata

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"Sivu {page_num}: kortteja ei löytynyt — mahdollinen esto tai selektorin muutos.")
            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"Sivu {page_num}: kaivettu {len(cards)} työpaikkaa")

        # Sivutus
        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

Tallenna CSV-muotoon

def save_to_csv(jobs, filename="glassdoor_jobs.csv"):
    if not jobs:
        print("Tallennettavaa dataa ei ole.")
        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"Tallennettu {len(jobs)} työpaikkaa tiedostoon {filename}")

Huomio sivutusrajoista: Glassdoor rajoittaa hakutulokset noin 30 sivuun kokonaismäärästä riippumatta. Jos tarvitset laajemman kattavuuden, käytä suodattimia (sijainti, työtyyppi, palkkahaarukka) ja pilko hakuja sen sijaan, että yrittäisit selata rajan yli.

Oman testini mukaan 5 sivun työpaikkailmoitusten kaapiminen (noin 75 työpaikkaa) vei satunnaisilla viiveillä noin 45 sekuntia. Saman tekeminen käsin veisi vähintään 20 minuuttia copy-pastea.

Vaihe 4: Kaavi Glassdoorin yritysarviot

Tämä on se osio, jolle yksikään muu opas ei tarjoa toimivaa koodia. Arviot ovat todellisen työnantaja-analyysin ytimessä — sentimentti, kulttuurisignaalit ja johtamisen varoitusmerkit.

Siirry arviot-sivulle

Arviosivujen URL-osoitteet noudattavat muotoa: /Reviews/{Company}-Reviews-E{id}.htm. Löydät employer ID:n etsimällä yrityksen Glassdoorista ja tarkistamalla URLin.

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)

Piilotettu BFF-endpoint (siistein reitti)

Tässä on tutkimukseni tärkein löydös: Glassdoorin arvioilla on toimiva sisäinen JSON-API, joka ohittaa HTML-jäsentämisen kokonaan. Scrapflyn scrapers-repositorio dokumentoi tämän endpointin, ja se on paljon luotettavampi kuin DOM-kaappaus.

import json, re, requests

def get_review_ids(page):
    """Poimi reviews-sivun HTML:stä employerId ja dynamicProfileId."""
    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):
    """Kutsu Glassdoorin sisäistä BFF-endpointia rakenteisen arvio­datan hakemiseksi."""
    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 palautti tilakoodin {resp.status_code} sivulla {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"Arviosivu {pg}/{total_pages}: saatu {len(reviews)} arviota")
        if pg >= total_pages:
            break
        time.sleep(random.uniform(3, 6))

    return all_reviews

BFF-endpoint antaa siistiä JSONia kaikilla arvioiden kentillä — ei HTML-jäsentämistä, ei CSS-selektorien rikkoutumista. Tarvitset vain kirjautuneen Playwright-session evästeet (käsitellään alla vaiheessa 6) sekä employerId- ja dynamicProfileId-arvot, jotka poimitaan ensin reviews-sivun HTML:stä.

HTML-varmistusselektorit arvioille

Jos BFF-endpoint muuttuu tai haluat mieluummin DOM-jäsentämistä, tässä ovat vakaat data-test-selektorit:

KenttäSelektori
Arviokortti[data-test="review"]
Otsikko[data-test="review-title"]
Kokonaisarvosana[data-test="overall-rating"]
Plussat[data-test="pros"]
Miinukset[data-test="cons"]
Päivämäärä[data-test="review-date"]
Kirjoittajan rooli[data-test="author-jobTitle"]

Vaihe 5: Kaavi Glassdoorin palkkatiedot

Palkkasivut ovat täysin kirjautumisen takana. Sinulla täytyy olla autentikoitu sessio (vaihe 6), ennen kuin tämä koodi palauttaa oikeaa dataa.

Siirry palkkasivulle

Palkka-URLit ovat muotoa: /Salary/{Company}-Salaries-E{id}.htm, ja sivutus käyttää muotoa _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"Palkkasivu {pg}: rivejä ei löytynyt — mahdollinen kirjautumismuuri tai esto.")
            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"Palkkasivu {pg}: kaivettu {len(items)} riviä")

    return all_salaries

Huomaa [class*="SalaryItem_jobTitle__"]-etuliitehaku. Glassdoorin palkkasivu käyttää CSS-moduulien hajautettuja luokkanimiä (esim. SalaryItem_jobTitle__XWGpT), joissa loppuosan hash vaihtuu jokaisessa deployssa. Etuliite pysyy vakaana — hash ei. Älä koskaan kovakoodaa koko luokkanimeä.

Vaihe 6: Pääse Glassdoorin kirjautumismuurin ohi

Tämä on kriittinen osa, joka avaa palkkatiedot ja täydet arvioiden tekstit. Lähestymistapa: kirjaudu kerran käsin näkyvässä selaimessa, tallenna autentikoitu sessio ja käytä sitä uudelleen kaikissa myöhemmissä kaappauksissa.

Tallenna autentikoitu sessio

Aja tämä skripti kerran. Se avaa Chrome-ikkunan, siirtyy Glassdoorin kirjautumissivulle (joka nykyään ohjaa Indeed Login -palveluun) ja odottaa, että kirjaudut sisään käsin:

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("Kirjaudu sisään selaimen ikkunassa ja paina sitten Enter täällä...")
        input()
        await context.storage_state(path=str(STATE_FILE))
        print(f"Sessio tallennettu tiedostoon {STATE_FILE}")
        await browser.close()

asyncio.run(login_and_save())

Kun olet kirjautunut ja painanut Enteriä, Patchright tallentaa kaikki evästeet ja paikallisen tallennuksen tiedostoon glassdoor_state.json. Tämä tiedosto sisältää gdId-, GSESSIONID-, cf_clearance- ja auth-tokenit.

Käytä sessiota uudelleen kaappauksessa

Kaikki myöhemmät ajot lataavat tallennetun tilan — käsin kirjautumista ei enää tarvita:

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

Tallennettu sessio kestää tavallisesti noin 20–30 minuuttia aktiivista käyttöä ennen kuin Glassdoor haastaa uudelleen. Pidemmissä ajoissa kannattaa lisätä tarkistus: jos sivulta, jolla pitäisi olla dataa, tulee nolla tulosta, aja kirjautumisskripti uudelleen ja päivitä tilatiedosto.

Kirjautumisponnahdusikkunan tunnistus ja sulkeminen

Osittain lukituilla sivuilla (työpaikkalistaukset, joissa data näkyy mutta modal peittää sen) aiempien vaiheiden CSS-injektio toimii:

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

Tämä toimii vain silloin, kun HTML sisältää jo itse datan peitteen alla. Täysin palvelinpuolelta lukituilla sivuilla (palkat, syvemmät arviointisivut) ainoa toimiva reitti on vaiheen 6 autentikoitu sessio.

Vinkkejä Glassdoor-kaapimesi pitämiseen toiminnassa

Glassdoor päivittää etupäätään usein. Näin rakennat kaapimesta kestävämmän.

Suosi data-test-attribuutteja luokkanimien sijaan

Glassdoor satunnaistaa CSS-luokkien nimet, mutta data-test-attribuutit pysyvät yleensä vakaina. Käytä aina mieluummin [data-test="jobListing"] kuin .jobCard_abc123. Kun data-test-attribuuttia ei ole (kuten palkkakenttien luokissa), käytä etuliitehakua: [class*="SalaryItem_jobTitle__"].

Kierrätä proxyt ja satunnaista viiveet

Käytä kiertäviä residential-proxyja — datakeskus-IP:t haastetaan lähes heti. Lisää sivulatausten väliin satunnaisia viiveitä 3–8 sekuntia (pidemmissä ajoissa 5–15 sekuntia). Jos mahdollista, vältä kaappaamista Yhdysvaltojen toimistoaikoina, jolloin Cloudflaren käyttäytymisen tunnistus on kaikkein aggressiivisinta.

Tarkkaile rikkoutumista

Rakenna kaapuriisi yksinkertainen tarkistus: jos sivu, jolla pitäisi olla dataa, palauttaa nolla poimittua riviä, käsittele sitä selektorivirheenä — ei tyhjänä tuloksena — ja hälytä itsellesi. Aja pieni testikaappaus viikoittain, jotta huomaat rikkoutumisen ajoissa — Glassdoor julkaisee etupään muutoksia ilmoittamatta.

Käytä __NEXT_DATA__-nopeuspolkua aina kun mahdollista

Glassdoor on Next.js + Apollo GraphQL -sovellus. Monilla sivuilla on <script id="__NEXT_DATA__"> -tagi, joka sisältää koko GraphQL-välimuistin JSON-muodossa. Sen jäsentäminen on paljon kestävämpää kuin DOM-kaappaus ja ohittaa täysin Hardsell-peitteen:

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

Tämä palauttaa rakenteisen Apollo-välimuistin, jossa ovat kaikki työpaikka-, arvio- ja palkkakentät — CSS-selektoreita ei tarvita. Tämä on kestävin mahdollinen poimintastrategia, koska se käyttää samaa dataa, joka pyörittää Glassdoorin React-etupäätä.

Ohita koodi: kaavi Glassdoor Thunderbitillä (ei Pythonia)

Kaikki tätä lukevat eivät ole kehittäjiä. Myös HR-tiimit, rekrytoijat, sales ops -analyytikot ja markkinatutkijat tarvitsevat Glassdoor-dataa — eikä heidän pitäisi joutua hallinnoimaan Playwright-sessioita ja proxyjen kierrätystä saadakseen sitä.

Thunderbit on AI Web Scraper -Chrome-laajennus, joka voi poimia samat työpaikka-, arvio- ja palkkatiedot ilman yhtäkään koodiriviä. Työskentelen Thunderbit-tiimissä, joten sanon tämän suoraan — mutta syy siihen, että otan tämän mukaan, on se, että se ratkaisee aidosti kaksi Glassdoor-kaappauksen vaikeinta ongelmaa.

Miten Thunderbit toimii Glassdoorissa

Työskentelytapa on kaksi klikkausta:

  1. Avaa mikä tahansa Glassdoor-sivu Chromessa (työpaikkahaku, yritysarviot, palkkasivu)
  2. Klikkaa Thunderbitin sivupalkissa AI Suggest Fields — tekoäly lukee sivun DOMin ja ehdottaa sarakkeita (työnimike, yritys, arvosana, palkkahaarukka, plussat, miinukset jne.)
  3. Klikkaa Scrape — data poimitaan taulukkoon ilman CSS-selektoreita tai selaimen automaatiokoodia

Thunderbitillä on valmis Glassdoor company scraper -malli, joka poimii yli 23 kenttää yritystä kohden yhdellä ajolla. Työpaikkailmoituksille, arvioille tai palkoille geneerinen AI Suggest Fields -työnkulku toimii kaikilla Glassdoor-URL:eilla.

Kirjautumismuurin käsittely ilman koodia

Tässä on Thunderbitin rakenteellinen etu juuri Glassdoorissa. Browser Mode toimii omassa Chrome-sessiossasi — jos olet kirjautuneena Glassdooriin Chromessa, Thunderbit käyttää samoja evästeitä automaattisesti. Palkka- ja arviointisivujen kirjautumismuuri, joka estää palvelinpuolen kaapimet, ei yksinkertaisesti ole esteenä. Ei evästehallintaa, ei pysyviä context-olioita, ei sessiokoodia.

Alisivujen kaappaus rikastamista varten

Aloita listanäkymästä (esim. 30 yritystä hakutuloksista), anna Thunderbitin lukea rivit, ja ota käyttöön subpage scraping, jotta se käy jokaisen yrityksen arvio- tai palkkasivulla ja rikastaa taulukon täydellisillä kuvauksilla, arvostelutekstillä tai palkkatiedoilla.

Vie tiedot liiketoimintatyökaluihin

Toisin kuin Python-skriptit, jotka tuottavat CSV:tä tai JSONia, Thunderbit vie tiedot suoraan Google Sheetsiin, Airtableen, Notioniin tai Exceliin — maksutta kaikilla suunnitelmilla. Tämä on erityisen hyödyllistä tiimeille, jotka haluavat jakaa ja analysoida dataa yhdessä.

Python vs. Thunderbit: milloin mitäkin?

TilanneSuositeltu tapa
Rakennat toistuvaa dataputkeaPython + Patchright
Kertaluontoinen tutkimus tai pienen tiimin projektiThunderbit
Tarvitset ohjelmallista kontrollia joka kentästäPython
Et ole kehittäjä, mutta tarvitset Glassdoor-dataa tänäänThunderbit
Kaapit 1 000+ sivua yhdellä ajollaPython + proxyt
Kaapit 30 yritystä rikastuksellaKumpikin toimii — Thunderbit on nopeampi ottaa käyttöön

Thunderbitin hinnoittelu alkaa ilmaisesta tasosta (6 sivua/kk), ja Pro-suunnitelma maksaa 38 dollaria kuukaudessa ja sisältää 3 000 krediittiä. Kun yksi krediitti vastaa yhtä tulosriviä (2 krediittiä alisivukaappauksessa), se riittää noin 33 ajokertaan, joissa käsitellään 30 rikastettua yritystä kuukaudessa.

Kokeile Thunderbitia Glassdoorin kaapimiseen

Onko Glassdoorin kaapiminen laillista?

Pidän tämän lyhyenä ja faktapohjaisena. Glassdoorin käyttöehdot kieltävät nimenomaisesti automatisoidun kaappauksen: "You may not use any robot, spider, scraper... to access the Services for any purpose without our express written permission."

Oikeudellinen maisema on kuitenkin monimutkaisempi kuin yksi käyttöehtolauseke:

  • Meta v. Bright Data (N.D. Cal., tammi 2024): Oikeus katsoi, että jos et koskaan kirjaudu sisään, et myöskään hyväksynyt käyttöehtoja, eikä julkisen uloskirjautuneen sisällön kaapiminen riko niitä
  • hiQ Labs v. LinkedIn (9th Cir.): CFAA ei koske julkisesti saatavilla olevan datan automatisoitua keruuta — mutta väärennetyt tilit ja kirjautuneena kaappaminen ovat eri asia
  • Van Buren v. United States (Korkein oikeus, 2021): Rajasi CFAA:n käsitettä "exceeds authorized access"

Käytännön yhteenveto: julkisten työpaikkailmoitusten kaapiminen ilman kirjautumista on suhteellisesti turvallisemmalla alueella. Kaappaus kirjautuneella sessiolla tarkoittaa, että hyväksyit käyttöehdot rekisteröityessäsi, ja ne kieltävät sen nimenomaisesti. Tämä koskee yhtä lailla Python-skriptejä ja Thunderbitin Browser Modea.

Seuraamisen arvoiset eettiset periaatteet joka tapauksessa:

  • Rajoita pyyntöjen määrä selvästi ihmisen selausnopeuden alapuolelle
  • Älä kaavi tai jälleenmyy henkilöön yhdistettävää arvioijadataa
  • Noudata robots.txt-ohjeita
  • Poimi vain ne kentät, joita oikeasti tarvitset

Yhteenveto: mikä menetelmä sopii sinulle?

Tässä oppaassa käsiteltiin kaikki kolme Glassdoor-datatyyppiä — työpaikat, arviot ja palkat — ja mukana oli toimiva vuoden 2025 koodi, joka huomioi Indeed Login -siirtymän, Cloudflare Bot Managementin sekä CSS-moduulien luokkanimien vaihtumisen, joka rikkoi kaikki vanhemmat oppaat.

Tässä päätöspuu:

TilanteesiParas polku
Kehittäjä, joka rakentaa dataputkeaPython + Patchright (noudata yllä olevaa vaiheittaista ohjetta)
Kertaluontoinen tutkimus tai toistuva pieni poimintaThunderbit (ei koodia, selainpohjainen)
Tarvitset vain perusluonteiset työpaikkailmoitukset pienessä mittakaavassaTarkista ensin, onko Glassdoor API-käyttö edelleen mahdollinen (todennäköisesti ei)
Tarvitset nimenomaan palkka- tai arviointidataaKäytä joko Python-kaappausta tai Thunderbitia — API ei koskaan kattanut näitä
Tiimi koostuu ei-kehittäjistä ja tarvitsee jaettua dataaThunderbit → vienti Google Sheetsiin

Glassdoorin puolustusmekanismit kehittyvät edelleen. Selektorit rikkoutuvat. Uusia haasteita ilmestyy. Tallenna tämä opas kirjanmerkkeihin — ja jos haluat syvemmälle web-kaappaustyökaluihin ja tekniikoihin, katso myös kirjoituksemme parhaista automatisoiduista web-kaappaustyökaluista, kuinka kaapata dataa verkkosivulta Pythonilla ja parhaista työnhakukaappaustyökaluista. Voit myös katsoa opastusvideoita Thunderbit YouTube -kanavalla.

Kokeile Thunderbitia Glassdoor-datan poimintaan Get Started Free

Usein kysytyt kysymykset

1. Voiko Glassdooria kaapia ilman kirjautumista?

Kyllä, useimpien työpaikkailmoitusten tietojen ja yritysten pääarvosanojen osalta. Ei, jos tarvitset täyden palkkarakenteen tai koko arvostelutekstin ensimmäisiä sivuja pidemmälle. #HardsellOverlay on vain CSS-muotoinen modaali — taustalla oleva HTML sisältää silti ensimmäisen sivun tiedot — mutta syvemmät sisällöt ovat palvelinpuolella Glassdoorin "give-to-get"-muurin takana.

2. Mikä Python-kirjasto toimii parhaiten Glassdoorin kaapimiseen vuonna 2025?

Patchright (Playwrightin stealth-haara) on oletussuositus. Se paikkaa Runtime.Enable CDP -vuodon, joka vakioversion Playwrightilla on ja jonka Cloudflare tarkistaa nimenomaisesti. Listasivuille, jotka toimittavat __NEXT_DATA__-datan alkuperäisessä HTML:ssä, curl_cffi parametrilla impersonate="chrome124" on 10–20 kertaa nopeampi, mutta se ei pysty käsittelemään kirjautumisen takana olevia sivuja.

3. Miten vältän blokkaamisen Glassdooria kaapatessa?

Käytä Patchrightia tai rebrowser-playwrightia (ei vakiota Playwrightia tai Seleniumia). Kierrätä residential-proxyja — datakeskus-IP:t haastetaan heti. Lisää satunnaiset 3–8 sekunnin viiveet sivujen väliin. Säilytä evästeet (gdId, cf_clearance, GSESSIONID) pyyntöjen välillä. Varaudu siihen, että sessioikkuna kestää noin 20–30 minuuttia ennen uutta haastetta.

4. Onko olemassa Glassdoor API, jota voisin käyttää kaapimisen sijaan?

Käytännössä ei. Vanha Partner API on suljettu uusilta hakijoilta, julkista reviews-endpointia ei koskaan ollut, eikä Indeedin Publisher API tarjoa migraatiopolkua. Kaappaus tai no-code-työkalu kuten Thunderbit on ainoa käytännöllinen vaihtoehto arvioille ja palkkatiedoille.

5. Kuinka usein Glassdoor-kaapimet rikkoutuvat?

Usein. Glassdoor julkaisee etupään muutoksia ilmoittamatta, ja CSS-moduulien luokkanimien hashit vaihtuvat jokaisessa buildissa. Vakain poiminta perustuu: (1) data-test-attribuuttiselektoreihin, (2) __NEXT_DATA__-JSON-lohkoon ja (3) sisäiseen BFF-arvio-endpointiin. Rakenna nolla tulosta -tarkistus ja aja pieni testikaappaus viikoittain, jotta havaitset rikkoutumisen ajoissa.

Lue lisää

Ke
Ke
Thunderbitin CTO | Senior Data Scientist & ML-asiantuntija Lähes vuosikymmenen kokemuksella koneoppimisesta ja data science -työstä Ke Shen on Columbia Universityn alumni ja entinen Senior Data Scientist Walmart Labsilla. Hänellä on syvällistä, alan kollegoiden tunnustamaa asiantuntemusta Pythonista, R:stä, Javasta ja tilastotieteestä, ja hän jakaa käytännössä koeteltuja oivalluksia siitä, miten monimutkaiset tekoälyalgoritmit viedään teoriasta tuotantokäyttöön sopivaksi arkkitehtuuriksi.
Sisällysluettelo

Poimi verkkosivu pelkällä pyynnöllä

Kerro mitä tarvitset selkeällä englannilla. Tai vielä parempaa, älä kerro mitään.

Kokeile Thunderbitiä ilmaista
Poimi dataa AI:n avulla
Siirrä data helposti Google Sheetiin, Airtableen tai Notioniin
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week