Indeed ist eines der größten Jobportale im Web und aggregiert Millionen von öffentlichen Stellenanzeigen aus verschiedenen Branchen, Unternehmen und Regionen. Jedes Inserat enthält strukturierte Signale, die für Arbeitsmarktforschung, Wettbewerbsanalysen von Recruitern und individuelle Jobsuchtools geeignet sind: einen Jobtitel, das einstellende Unternehmen, einen Standort, eine Gehaltsspanne (sofern öffentlich) und einen Link zur vollständigen Anzeige. Der Haken ist, dass Indeed seine Suchergebnisse mit JavaScript aufbaut und die Inserat-Daten tief in die Seite einbettet, sodass eine einfache HTTP-Anfrage eine nahezu leere Hülle zurückgibt statt der gesuchten Stellen.
Dieser Leitfaden zeigt Ihnen, wie Sie Indeed-Stellenanzeigen scrapen mit Python auf zuverlässige Weise. Sie erstellen einen kleinen, lauffähigen Scraper, der eine gerenderte Suchseite über die Crawling API abruft, die eingebetteten Job-Daten aus der Seite extrahiert, jedes Feld parst, die Paginierung behandelt und die Ergebnisse als JSON und CSV exportiert. Die gesamte Anleitung beschränkt sich auf öffentliche Stellenanzeigen, und der Abschnitt zur Rechtslage am Ende ist kein Boilerplate, also lesen Sie ihn, bevor Sie den Scraper auf ein größeres Volumen ansetzen.
Was Sie erstellen werden
Ein Python-Skript, das eine öffentliche Indeed-Such-URL übernimmt, das gerenderte HTML über die Crawling API abruft und für jede Anzeige auf der Seite einen strukturierten Datensatz extrahiert. Als laufendes Beispiel verwenden wir eine Suche nach Entwicklerjobs und lesen folgende Felder je Anzeige:
-
Jobtitel die ausgeschriebene Rolle, gelesen aus dem
title-Feld jeder Karte. - Unternehmen der Arbeitgeber hinter dem Inserat.
-
Standort wo die Stelle angesiedelt ist, aus
formattedLocation. -
Gehaltsspanne das Mindest- und Maximalgehalt, wenn Indeed es ausgibt, aus
extractedSalary. -
Job-Key und Link der
jobkey-Bezeichner und die Anzeigen-URL, damit Sie bei Bedarf pro Stelle nachfassen können.
Warum eine einfache Anfrage bei Indeed scheitert
Wenn Sie eine Indeed-Such-URL mit einem einfachen HTTP-Client aufrufen, erhalten Sie eine Antwort mit Status 200 und fast keine Inserat-Daten im Body. Zwei Dinge arbeiten gegen Sie. Erstens rendert Indeed seine Ergebnisse mit JavaScript, sodass das anfängliche HTML eine Hülle ist, die sich erst nach dem Ausführen der Skripte füllt. Zweitens schützt Indeed aktiv gegen automatisierten Zugriff mit CAPTCHA-Herausforderungen und IP-basierten Rate-Limits, sodass selbst eine gerenderte Anfrage von einer markierten IP eine Challenge-Seite statt Stellenanzeigen erhält.
Ein funktionierender Indeed-Scraper braucht also zwei Dinge in einer einzigen Anfrage: einen Browser, der die Seite tatsächlich rendert, und eine IP, die die Plattform als echten Besucher erkennt. Sie können das selbst mit einem Headless-Browser und einem Pool aus rotierenden Residential-Proxys zusammensetzen, aber das Zusammenhalten dieses Stacks ist der größte Teil der Arbeit. Die Crawling API fasst beides in einem einzigen Aufruf zusammen: Sie senden ihr die URL mit einem JavaScript-Token, sie rendert die Seite hinter einer vertrauenswürdigen IP und gibt fertiges HTML zurück, das Sie parsen können.
Crawlbase bietet zwei Token-Typen. Das normale Token ruft statisches HTML ab; das JavaScript-Token (JS-Token) rendert die Seite zuerst in einem echten Browser. Indeed ist clientseitig gerendert, daher benötigen Sie hier das JS-Token. Das normale Token gibt dieselbe leere Hülle zurück wie eine einfache Abfrage, und es gibt darin nichts zu parsen.
Voraussetzungen
Sie benötigen einige Vorbereitungen, bevor Sie Code schreiben. Keine davon dauert lange.
Python-Grundkenntnisse. Sie sollten in der Lage sein, ein Python-Skript zu schreiben und auszuführen sowie Pakete mit pip zu installieren. Das Parsen hier stützt sich auf reguläre Ausdrücke und JSON statt auf eine DOM-Bibliothek, aber wenn Sie auch eine Einführung auf Basis von Selektoren wünschen, erklärt unser Leitfaden zu BeautifulSoup in Python die Grundlagen.
Python 3.8 oder höher. Bestätigen Sie Ihre Version mit python --version. Falls nicht vorhanden, installieren Sie es von python.org oder über eine Distribution wie Anaconda.
Ein Crawlbase-Konto und ein JS-Token. Registrieren Sie sich, öffnen Sie Ihr Dashboard und kopieren Sie Ihr JavaScript-Token (JS-Token) von der Kontodokumentationsseite. Behandeln Sie das Token wie ein Passwort: Es authentifiziert Ihre Anfragen, halten Sie es daher aus der Versionskontrolle heraus. Das kostenlose Kontingent umfasst bis zu 20.000 Anfragen, genug um diese Anleitung vollständig zu durchlaufen, und es wird nur für erfolgreiche Anfragen abgerechnet.
Projekt einrichten
Erstellen Sie eine virtuelle Umgebung, um Projektabhängigkeiten isoliert zu halten, und installieren Sie dann die eine Bibliothek, die der Scraper benötigt.
python --version python -m venv indeed_env source indeed_env/bin/activate pip install crawlbase
Unter Windows aktivieren Sie die Umgebung mit indeed_env\Scripts\activate statt der source-Zeile. Das crawlbase-Paket ist der offizielle Client für die Crawling API. Da Indeed seine Inserat-Daten als JSON in die Seite einbettet, übernehmen die Standardbibliotheksmodule re und json das Parsen, sodass für die Suchseiten keine HTML-Bibliothek installiert werden muss.
Schritt 1: Die gerenderte Suchseite abrufen
Beginnen Sie damit, die fertige Seite zu laden. Wenn Sie eine Suche auf Indeed starten, werden Sie zu einer URL wie https://www.indeed.com/jobs?q=Web+Developer&l=Virginia weitergeleitet, wobei q die Suchanfrage und l der Standort ist. Importieren Sie die CrawlingAPI-Klasse, initialisieren Sie sie mit Ihrem JS-Token und fragen Sie diese URL ab. Übergeben Sie country, damit die Anfrage von einer US-IP kommt, da Indeed lokalisierte Ergebnisse liefert. Die Statusprüfung vor dem Parsen macht Fehler laut statt still.
from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def crawl(page_url): response = api.get(page_url, {"country": "US"}) if response["status_code"] == 200: return response["body"].decode("latin1") print(f"Request failed: {response['status_code']}") return None if __name__ == "__main__": page_url = "https://www.indeed.com/jobs?q=Web+Developer&l=Virginia" html = crawl(page_url) print(html[:500] if html else "No HTML returned")
Führen Sie das Skript mit python scraper.py aus und Sie sollten echtes Seiten-Markup sehen, keine leere Hülle wie bei einer einfachen Abfrage. Wir dekodieren mit latin1 statt utf-8, weil Indeed-Seiten gemischte Byte-Sequenzen enthalten, und latin1 bildet jedes Byte sauber ab, sodass das eingebettete JSON die Dekodierung intakt übersteht. Damit bestätigen Sie, dass das Rendering funktioniert, bevor Sie einen einzigen Parser schreiben.
Indeed benötigt eine JavaScript-gerenderte Seite hinter einer vertrauenswürdigen IP, in einem einzigen Aufruf, sonst stoppen Sie CAPTCHA und Rate-Limits sofort. Die Crawling API nimmt ein JS-Token, führt die Seite in einem echten Browser aus und rotiert serverseitig durch Residential-IPs, sodass Sie keinen eigenen Headless-Fleet und keinen Proxy-Pool betreiben müssen. Testen Sie es zunächst mit einer öffentlichen Suchseite im kostenlosen Kontingent.
Schritt 2: Die eingebetteten Job-Daten lokalisieren
Sie könnten die gerenderten Job-Karten mit CSS- oder XPath-Selektoren parsen, aber Indeed bietet Ihnen einen einfacheren und wesentlich stabileren Anker. Jede Suchseite bettet den vollständigen Satz von Inseraten als JSON-Dokument in einem Script-Tag ein, das einer JavaScript-Variable namens window.mosaic.providerData["mosaic-provider-jobcards"] zugewiesen ist. Dieses einzelne Blob gibt Ihnen alle Felder, die die Karten anzeigen, bereits strukturiert, ohne den Markup-Wandel, der klassenbasierte Selektoren bricht.
Ein kurzer regulärer Ausdruck zieht dieses JSON aus dem HTML. Nach dem Parsen befinden sich die Inserate unter einem vorhersehbaren Pfad, und ein Geschwisterblock enthält die Ergebniszahlen, die Sie für die Paginierung benötigen:
import re import json def parse_search_page_html(html): data = re.findall(r'window.mosaic.providerData\["mosaic-provider-jobcards"\]=(\{.+?\});', html) data = json.loads(data[0]) model = data["metaData"]["mosaicProviderJobCardsModel"] return { "results": model["results"], "meta": model["tierSummaries"], }
Die Funktion lokalisiert die mosaic-provider-jobcards-Variable, parst das JSON und gibt zwei Teile zurück: results, die Liste der Stellenanzeigen, und meta, die Tier-Zusammenfassungen, die angeben, wie viele Stellen in den Kategorien übereinstimmen. Jeder Eintrag in results ist ein umfangreiches Objekt, aber Sie benötigen nur eine Handvoll seiner Felder für einen sauberen Datensatz.
Schritt 3: Die gewünschten Felder extrahieren
Ein rohes Inserat-Objekt enthält Dutzende interner Keys. Reduzieren Sie jede Karte auf die relevanten Felder und sichern Sie die optionalen ab, damit ein fehlendes Gehalt den Lauf nie zum Absturz bringt. Das Gehalt liegt unter extractedSalary als Minimum, Maximum und Typ, wenn Indeed es angibt, und der Posting-Link wird aus dem jobkey erstellt.
def format_salary(card): salary = card.get("extractedSalary") if not salary: return "" low, high = salary.get("min"), salary.get("max") unit = salary.get("type", "") if low == high: return f"{low} {unit}".strip() return f"{low}-{high} {unit}".strip() def extract_jobs(results): jobs = [] for card in results: job_key = card.get("jobkey", "") jobs.append({ "title": card.get("title", ""), "company": card.get("company", ""), "location": card.get("formattedLocation", ""), "salary": format_salary(card), "posted": card.get("formattedRelativeTime", ""), "job_key": job_key, "link": f"https://www.indeed.com/viewjob?jk={job_key}", }) return jobs
Jeder Feldzugriff erfolgt über .get() mit einem Standardwert, sodass ein Inserat ohne Gehalt oder Unternehmensname einen leeren String statt eines KeyError liefert. Der jobkey lohnt es sich, separat aufzubewahren: Er identifiziert ein Inserat eindeutig und ermöglicht einen direkten viewjob-Link, der nützlich ist, wenn Sie später die vollständige Stellenbeschreibung einer einzelnen Rolle abrufen möchten.
Der mosaic-provider-jobcards-Variablenname und die obigen Feld-Keys spiegeln die aktuelle Seitenstruktur von Indeed wider und können sich bei einem Redesign ändern. Behandeln Sie sie als Ausgangspunkt, nicht als Vertrag. Wenn der reguläre Ausdruck keine Übereinstimmungen mehr findet oder ein Feld bei jeder Karte leer zurückkommt, inspizieren Sie erneut eine Live-Suchseite in den Entwicklertools Ihres Browsers, finden Sie das eingebettete JSON erneut und aktualisieren Sie das Muster. Regelmäßige Wartung ist normal für jeden produktiven Scraper.
Schritt 4: Paginierung behandeln
Eine Suchseite zeigt nur den ersten Stapel von Stellen. Indeed paginiert mit einem start-Query-Parameter, der die Ergebnisse in Schritten von 10 versetzt, sodass Sie durch Erhöhen dieses Parameters weiter in die Ergebnisse vordringen. Die Tier-Zusammenfassungen aus Schritt 2 zeigen Ihnen, wie viele Stellen insgesamt übereinstimmen, was Ihnen ermöglicht, das Crawling bei einem sinnvollen max_results zu begrenzen statt jede Seite abzurufen. Erstellen Sie jede Seiten-URL mit urlencode, rufen Sie sie ab und akkumulieren Sie die extrahierten Datensätze.
import time from urllib.parse import urlencode def make_search_url(query, location, offset): params = {"q": query, "l": location, "filter": 0, "start": offset} return f"https://www.indeed.com/jobs?{urlencode(params)}" def scrape_indeed_search(query, location, max_results=50): print(f"Scraping first page: query={query}, location={location}") html = crawl(make_search_url(query, location, 0)) if not html: return [] first = parse_search_page_html(html) jobs = extract_jobs(first["results"]) total = sum(c["jobCount"] for c in first["meta"]) total = min(total, max_results) for offset in range(10, total, 10): print(f"Scraping page at offset {offset}") page_html = crawl(make_search_url(query, location, offset)) if page_html: page = parse_search_page_html(page_html) jobs.extend(extract_jobs(page["results"])) time.sleep(2) return jobs
Die erste Anfrage erfüllt zwei Zwecke: Sie liefert die erste Seite mit Stellen und die Tier-Zusammenfassungen, die die Gesamtanzahl der Treffer offenbaren. Von dort generiert die Schleife Seiten-URLs bei Offsets von 10 bis zur Obergrenze und ruft jede ab, wobei dasselbe Parse-und-Extrahier-Paar wiederverwendet wird. Das time.sleep(2) zwischen den Seiten ist bewusst gesetzt. Anfragen in schneller Folge zu senden ist der schnellste Weg, gedrosselt zu werden, selbst wenn Rendering und Rotation für Sie übernommen werden.
Schritt 5: Alles zusammensetzen und JSON und CSV exportieren
Verbinden Sie nun den Abruf, den Parser, den Feldextraktor und die Paginierungsschleife zu einem einzigen lauffähigen Skript und schreiben Sie dann die Datensätze sowohl als JSON als auch als CSV. JSON bewahrt die Struktur für nachgelagerten Code; CSV öffnet sich direkt in einer Tabellenkalkulation.
import re import json import csv import time from urllib.parse import urlencode from crawlbase import CrawlingAPI api = CrawlingAPI({"token": "YOUR_CRAWLBASE_JS_TOKEN"}) def crawl(page_url): response = api.get(page_url, {"country": "US"}) if response["status_code"] == 200: return response["body"].decode("latin1") print(f"Request failed: {response['status_code']}") return None def parse_search_page_html(html): data = re.findall(r'window.mosaic.providerData\["mosaic-provider-jobcards"\]=(\{.+?\});', html) data = json.loads(data[0]) model = data["metaData"]["mosaicProviderJobCardsModel"] return {"results": model["results"], "meta": model["tierSummaries"]} def format_salary(card): salary = card.get("extractedSalary") if not salary: return "" low, high = salary.get("min"), salary.get("max") unit = salary.get("type", "") if low == high: return f"{low} {unit}".strip() return f"{low}-{high} {unit}".strip() def extract_jobs(results): jobs = [] for card in results: job_key = card.get("jobkey", "") jobs.append({ "title": card.get("title", ""), "company": card.get("company", ""), "location": card.get("formattedLocation", ""), "salary": format_salary(card), "posted": card.get("formattedRelativeTime", ""), "job_key": job_key, "link": f"https://www.indeed.com/viewjob?jk={job_key}", }) return jobs def make_search_url(query, location, offset): params = {"q": query, "l": location, "filter": 0, "start": offset} return f"https://www.indeed.com/jobs?{urlencode(params)}" def scrape_indeed_search(query, location, max_results=50): html = crawl(make_search_url(query, location, 0)) if not html: return [] first = parse_search_page_html(html) jobs = extract_jobs(first["results"]) total = min(sum(c["jobCount"] for c in first["meta"]), max_results) for offset in range(10, total, 10): page_html = crawl(make_search_url(query, location, offset)) if page_html: jobs.extend(extract_jobs(parse_search_page_html(page_html)["results"])) time.sleep(2) return jobs def save_results(jobs): with open("indeed_jobs.json", "w") as f: json.dump(jobs, f, indent=2) if jobs: with open("indeed_jobs.csv", "w", newline="") as f: writer = csv.DictWriter(f, fieldnames=jobs[0].keys()) writer.writeheader() writer.writerows(jobs) def main(): jobs = scrape_indeed_search("Web Developer", "Virginia") save_results(jobs) print(f"Saved {len(jobs)} jobs to indeed_jobs.json and indeed_jobs.csv") if __name__ == "__main__": main()
Wie die Ausgabe aussieht
Führen Sie das vollständige Skript mit python scraper.py aus und Sie erhalten eine Liste sauberer strukturierter Datensätze, einen pro Inserat, die sowohl in indeed_jobs.json als auch indeed_jobs.csv geschrieben werden.
[ { "title": "Front Desk Agent", "company": "The Inn at Little Washington", "location": "Washington, VA 22747", "salary": "22 hourly", "posted": "20 days ago", "job_key": "72ed373141879fd4", "link": "https://www.indeed.com/viewjob?jk=72ed373141879fd4" }, { "title": "Web Developer", "company": "Acme Digital", "location": "Richmond, VA", "salary": "75000-95000 yearly", "posted": "3 days ago", "job_key": "6a45faa5d8d817fa", "link": "https://www.indeed.com/viewjob?jk=6a45faa5d8d817fa" } ]
Inserate ohne öffentliches Gehalt geben einen leeren salary-String zurück, was zu erwarten ist, da nicht jeder Arbeitgeber das Gehalt veröffentlicht. Dieselben Datensätze befinden sich in der CSV mit einer Zeile pro Stelle, bereit zum Öffnen in einer Tabellenkalkulation oder zum Laden in eine Datenbank zur Analyse.
Ungeblockt bleiben
Selbst wenn Rendering und Rotation erledigt sind, beobachtet Indeed den Traffic genau auf Scraper-typische Muster und gehört zu den aggressiveren Job-Portalen dabei. Einige Gewohnheiten halten einen Lauf gesund, und sie gelten für jedes schwierige kommerzielle Ziel.
-
Anfragen dosieren. Halten Sie das
time.sleepzwischen den Seiten ein und variieren Sie Ihre Suchanfragen, statt einen Suchpfad mit voller Geschwindigkeit zu crawlen. - Auf Rotation setzen. Ein Pool von Residential-IPs verteilt Anfragen auf viele echte Benutzeradressen, sodass keine einzelne ein Rate-Limit auslöst. Die Crawling API übernimmt das für Sie; wenn Sie Ihren eigenen Stack aufbauen, ist das der Teil, den Sie richtig machen müssen.
- Status-Codes beachten. Ein Lauf, der beginnt, CAPTCHA-Herausforderungen oder Nicht-200-Codes zurückzugeben, signalisiert Ihnen, dass die aktuelle Rate oder IP-Tier nicht mehr ausreicht. Behandeln Sie das als Signal zum Zurückschalten, nicht als Rauschen zum Ignorieren.
Das umfassendere Playbook finden Sie unter wie man Websites scrapt, ohne geblockt zu werden und in unserem ausführlicheren Artikel über wie man JavaScript-Websites crawlt, der das Rendering-Problem behandelt, das die meisten Job-Portal-Scraper scheitern lässt. Wenn Sie einen breiteren Job-Datensatz erstellen, funktioniert dasselbe JSON-Extraktionsmuster auf anderen Portalen: Lesen Sie dazu Monster-Jobs mit Python scrapen und Glassdoor scrapen.
Ist es legal, Indeed zu scrapen?
Ob das Scrapen von Indeed erlaubt ist, hängt von Indeed's Nutzungsbedingungen, Ihrer Rechtsordnung und dem Zweck der Datennutzung ab. Indeed's Bedingungen schränken automatisierten Zugriff ein, und die Seite setzt aktiv CAPTCHAs und Rate-Limits ein, um ihn zu entmutigen, sodass das Scrapen gegen diese Bedingungen verstoßen kann, unabhängig davon, wie sorgfältig Ihr Tooling ist. Keiner der hier gezeigten Code-Teile ändert das; er lässt nur den technischen Teil funktionieren. Lesen Sie Indeed's Nutzungsbedingungen und seine robots.txt, und behandeln Sie beides als Grenze für das, was Sie erheben.
Einige Grundregeln, an die Sie sich halten sollten. Sammeln Sie nur öffentliche Stellenanzeigen-Daten: den Jobtitel, das Unternehmen, den Standort, die öffentliche Gehaltsspanne und den Posting-Link, den jeder auf einer öffentlichen Suchseite ohne Anmeldung sehen kann. Respektieren Sie Indeed's Erwartungen an die Anfragerate und halten Sie Ihr Anfragevolumen niedrig genug, dass Sie die Server nicht belasten. Wenn personenbezogene Daten im Spiel sind, gelten Datenschutzgesetze wie DSGVO und CCPA, daher begrenzen Sie Ihre Arbeit strikt auf das öffentliche Inserat selbst.
Dieser Leitfaden beschränkt sich bewusst auf öffentliche Stellenanzeigen, weil das die Grenze ist, die die Arbeit verteidigbar hält. Er behandelt nicht Bewerberdaten, Lebensläufe, Kandidatenprofile, Recruiter-Kontaktdaten oder irgendetwas hinter einem Login oder einem kostenpflichtigen Tier, und er versucht nicht, Authentifizierung zu umgehen. Persönliche Informationen von Stellensuchenden und Recruitern sind genau die Art von Daten, die man in Ruhe lassen sollte. Indeed betreibt auch eine offizielle Publisher-API und ein Partnerprogramm für lizenzierten Zugang zu Jobdaten, und wenn Ihr Projekt mehr als öffentliche Inserate in großem Maßstab benötigt, ist dieses Programm der richtige Weg, kein raffinierterer Scraper.
Wichtigste Erkenntnisse
- Indeed ist JavaScript-gerendert und geschützt. Eine einfache Anfrage gibt eine leere Hülle zurück und eine markierte IP erhält ein CAPTCHA, daher müssen Sie hinter einer vertrauenswürdigen IP rendern, bevor Sie parsen.
-
Die Daten sind eingebettet, nicht im Markup. Jede Suchseite versteckt ihre Inserate als JSON in der
mosaic-provider-jobcards-Variable; ein kurzer regulärer Ausdruck plusjson.loadsist stabiler als CSS-Selektoren. -
Nur die benötigten Felder mappen. Titel, Unternehmen,
formattedLocation,extractedSalaryund denjobkey-Link extrahieren, wobei optionale Felder abgesichert werden, damit ein fehlendes Gehalt den Lauf nie abbricht. -
Mit start paginieren und beide Formate exportieren. Den
start-Parameter in Schritten von 10 bis zur Obergrenze aus den Tier-Zusammenfassungen durchlaufen, dann JSON und CSV schreiben. - Auf öffentliche Inserate beschränken. Indeed's ToS und robots.txt respektieren, für große Mengen die offizielle Publisher-API bevorzugen und niemals Bewerber- oder Recruiter-Personendaten berühren.
Häufig gestellte Fragen
Ist es möglich, Indeed zu scrapen?
Technisch ja, aber Indeed schützt sich dagegen mit CAPTCHA-Herausforderungen und IP-basierten Rate-Limits, und seine Bedingungen schränken automatisierten Zugriff ein. Um eine öffentliche Suchseite abzurufen, muss die Seite in einem echten Browser hinter einer vertrauenswürdigen IP gerendert werden, was das JS-Token der Crawling API erledigt, bevor Sie überhaupt parsen. Für lizenzierten Zugang in großem Maßstab sind die offizielle Publisher-API und das Partnerprogramm von Indeed der genehmigte Weg.
Brauche ich das normale Token oder das JS-Token für Indeed?
Das JS-Token. Indeed rendert seine Ergebnisse mit JavaScript, daher gibt das normale Token dieselbe leere Hülle zurück wie eine einfache Anfrage. Das JS-Token rendert die Seite zuerst in einem echten Browser, was dafür sorgt, dass das eingebettete mosaic-provider-jobcards-JSON im HTML vorhanden ist, das Sie parsen.
Warum eingebettetes JSON statt CSS-Selektoren parsen?
Indeed liefert die vollständigen Inserat-Daten als JSON-Blob innerhalb der Seite, zugewiesen an window.mosaic.providerData["mosaic-provider-jobcards"]. Dieses eine Objekt zu lesen gibt Ihnen alle Felder bereits strukturiert, und es übersteht die gehashten, build-generierten Klassennamen, die sektorbasierte Scraper bei jedem Deploy brechen. Ein einzelner regulärer Ausdruck extrahiert es, dann wandelt json.loads es in ein Python-Dictionary um.
Wie gehe ich mit Indeed's Paginierung um?
Indeed versetzt Ergebnisse mit einem start-Query-Parameter in Schritten von 10. Lesen Sie die Gesamttrefferzahl aus den Tier-Zusammenfassungen auf der ersten Seite, begrenzen Sie sie auf ein sinnvolles max_results, generieren Sie dann Seiten-URLs bei Offsets von 10, 20, 30 und so weiter, und rufen Sie jede ab und parsen Sie sie. Dosieren Sie die Schleife mit einem kurzen Schlaf, damit Sie nicht gedrosselt werden.
Kann ich Bewerberdaten oder vollständige Lebensläufe von Indeed scrapen?
Nein, und dieser Leitfaden behandelt das nicht. Bewerberdaten, Lebensläufe und Kandidaten- oder Recruiter-Profile sind personenbezogene Daten oder befinden sich hinter einem Login, keine öffentlichen Stellenanzeigen-Daten. Das Scrapen von login-gesperrten Inhalten oder das Umgehen von Authentifizierung verstößt gegen Indeed's Bedingungen und löst Datenschutzgesetze wie DSGVO und CCPA aus. Beschränken Sie Ihren Umfang auf die öffentlichen Inserate auf Suchseiten.
Wie vermeide ich Blocking beim Scrapen von Indeed?
Halten Sie Ihre pro-IP-Anfragerate niedrig, variieren Sie Ihre Anfragen statt eine Suchroute zu durchlaufen, und leiten Sie über rotierende Residential-IPs weiter, sodass keine einzelne Adresse ein Rate-Limit auslöst. Die Crawling API verwaltet Rotation und einen vertrauenswürdigen IP-Pool für Sie; wenn Sie Ihren eigenen Stack aufbauen, ist das der Teil, in den Sie investieren sollten. Beobachten Sie die Status-Codes und schalten Sie zurück, sobald Sie CAPTCHA-Herausforderungen sehen.
Crawlen Sie jede Website im großen Maßstab, ohne gegen die Infrastruktur zu kämpfen.
Crawlbase übernimmt Proxys, Fingerprints und CAPTCHAs, damit Ihr Team Datenpipelines ausliefert, statt Crawl-Infrastruktur zu pflegen. 1.000 Anfragen kostenlos, keine Karte erforderlich.
