Just Eat ist einer der größten Online-Marktplätze für Essenslieferungen in Europa und verbindet Millionen von Gästen mit lokalen Restaurants. Jede Gebietsseite ist ein öffentlicher, strukturierter Katalog darüber, wer in der Nähe liefert: der Name des Restaurants, die Küchen, die es zubereitet, seine Sternebewertung, die Lieferdetails und ein Link direkt zur Speisekarte. Diese Daten sind ein sauberes Signal für alle, die lokale Lebensmittelmärkte untersuchen, verfolgen wollen, welche Küchen eine Postleitzahl dominieren, Menüpreise vergleichen oder ein Tool zur Restaurantsuche bauen.

Diese Anleitung zeigt Ihnen, wie Sie Just-Eat-Daten scrapen mit Python. Sie bauen einen kleinen, lauffähigen Scraper, der über die Crawling API eine Just-Eat-Gebietsseite abruft, für jedes Restaurant einen sauberen Datensatz parst, einem Restaurant-Link folgt, um dessen Menüpunkte zu holen, die scrollbasierte Paginierung der Seite handhabt und die Ergebnisse nach JSON und CSV exportiert. Die gesamte Anleitung bleibt auf öffentliche Listendaten beschränkt: die Namen, Küchen, Bewertungen, Links und Menüpreise, die jeder auf einer Gebiets- oder Menüseite sehen kann, ohne sich anzumelden.

Was Sie bauen werden

Ein Python-Skript, das eine Just-Eat-Gebiets-URL entgegennimmt, die gerenderte Seite über die Crawling API abruft und pro Restaurant einen strukturierten Datensatz extrahiert. Wir verwenden die Gebietsseite von London Bridge als laufendes Beispiel, dasselbe Gebiet, das die alte Anleitung verwendet hat, und ziehen diese Felder aus jeder Restaurant-Karte:

  • Name der Restaurantname, der auf der Listenkarte angezeigt wird.
  • Küche die Küchen-Tags, zum Beispiel "Pizza, Italian".
  • Bewertung die Sternebewertung und die Anzahl der Rezensionen, zum Beispiel "4.5(26)".
  • Link die absolute URL zur eigenen Menüseite des Restaurants.
  • Menüpunkte pro Gericht die Kategorie, der Name, der Preis und die Beschreibung von der Menüseite des Restaurants.

Warum eine einfache Anfrage bei Just Eat scheitert

Wenn Sie einen schlichten HTTP-Client auf eine Just-Eat-Gebiets-URL richten, erhalten Sie nur selten die Restaurantliste, wegen der Sie gekommen sind. Zwei Dinge arbeiten gegen Sie. Erstens rendert Just Eat seine Listen clientseitig: Der Server liefert eine leichtgewichtige Hülle, und die Karten füllen sich, während das JavaScript der Seite läuft und während Sie scrollen, sodass das anfängliche HTML oft ein leeres Raster ist. Zweitens erkennt die Seite automatisierten Traffic schnell. Rechenzentrums-IPs und Anfragemuster, die nicht wie ein echter Browser aussehen, werden mit einer Challenge-Seite, einem CAPTCHA oder einer direkten Sperre beantwortet.

Ein funktionierender Just-Eat-Scraper braucht also zwei Dinge in einer Anfrage: einen Browser, der die Seite rendert, und eine IP, die die Seite als echten Besucher liest. Sie können das selbst mit einem Headless-Browser und einem Pool aus rotierenden Residential-Proxys zusammenstellen, aber diesen Stack gesund zu halten ist der größte Teil der Arbeit. Die Crawling API fasst beides in einem einzigen Aufruf zusammen: Sie senden ihr die Gebiets-URL, sie rendert die Seite hinter einer vertrauenswürdigen Residential-IP, übernimmt die Rotation und das Lösen von CAPTCHAs und liefert fertiges HTML zurück, das Sie parsen können.

Voraussetzungen

Ein paar Dinge müssen vorhanden sein, bevor Sie Code schreiben. Keines davon dauert lange.

Grundlegende Python-Kenntnisse. Sie sollten sich damit wohlfühlen, ein Python-Skript zu schreiben und auszuführen und Pakete mit pip zu installieren. Wenn Sie neu in der Sprache sind, decken die offizielle Python-Dokumentation oder ein beliebiger Anfängerkurs das Niveau ab, das dieses Tutorial voraussetzt.

Python 3.8 oder neuer. Bestätigen Sie Ihre Version mit python --version (oder python3 --version). Falls Sie es nicht haben, installieren Sie es von python.org und stellen Sie sicher, dass Python in Ihrem System-PATH liegt.

Ein Crawlbase-Konto und ein Token. Registrieren Sie sich für ein kostenloses Konto, öffnen Sie Ihr Dashboard und kopieren Sie Ihr Token. Crawlbase stellt zwei Tokens aus: ein normales Token für statische Seiten und ein JavaScript-Token für JS-gerenderte Seiten wie Just Eat. Die kostenlose Stufe umfasst bis zu 20.000 Anfragen ohne Karte. Behandeln Sie das Token wie ein Passwort und halten Sie es aus der Versionskontrolle heraus.

Das Projekt einrichten

Erstellen Sie eine virtuelle Umgebung, damit die Projektabhängigkeiten isoliert bleiben, und installieren Sie dann die beiden Bibliotheken, die der Scraper braucht. crawlbase ist der offizielle Client für die Crawling API, und beautifulsoup4 parst das zurückgegebene HTML, sodass Sie jedes Feld per CSS-Selektor aus den Restaurant-Karten ziehen können.

bash
python --version

python -m venv just_eat_env
source just_eat_env/bin/activate

pip install crawlbase beautifulsoup4

Unter Windows aktivieren Sie die Umgebung mit just_eat_env\Scripts\activate statt mit der source-Zeile. Wenn beide Bibliotheken installiert sind, erstellen Sie die Skriptdatei, die der Rest der Anleitung aufbaut:

bash
touch just_eat_scraper.py

Die Gebietsseite inspizieren, um Selektoren zu finden

Um Daten zu scrapen, müssen Sie zunächst verstehen, wie die Just-Eat-Gebietsseite aufgebaut ist. Öffnen Sie eine Gebietsseite in Ihrem Browser, zum Beispiel die Seite https://www.just-eat.co.uk/area/ec4r3tn für das Gebiet London Bridge, klicken Sie mit der rechten Maustaste auf eine Restaurant-Karte und wählen Sie Untersuchen. Just Eat kennzeichnet seine Schlüsselelemente mit stabilen data-qa-Attributen, die weit beständiger sind als seine generierten Utility-Klassennamen. Dies sind die Elemente, auf die Sie abzielen:

  • Restaurant-Karte: ein <div> mit data-qa="restaurant-card" umschließt jeden Eintrag.
  • Restaurantname: ein <div> mit data-qa="restaurant-info-name".
  • Küchentyp: ein <div> mit data-qa="restaurant-cuisine".
  • Bewertung: ein <div> mit data-qa="restaurant-ratings".
  • Restaurant-Link: das href auf dem <a>-Tag innerhalb der Karte, das relativ ist, also stellen Sie ihm https://www.just-eat.co.uk voran.

Schritt 1: Die gerenderte Gebietsseite abrufen

Beginnen Sie damit, die fertige Seite zu holen. Importieren Sie die Klasse CrawlingAPI, initialisieren Sie sie mit Ihrem Token, setzen Sie die Gebiets-URL und fordern Sie sie an. Der Inhalt von Just Eat lädt asynchron, also übergeben Sie ajax_wait, um auf den dynamischen Inhalt zu warten, und page_wait, um nach dem Laden ein paar Sekunden zu halten. Den Statuscode vor dem Parsen zu prüfen sorgt dafür, dass Fehler laut statt still bleiben.

python
from crawlbase import CrawlingAPI

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})

def fetch_listings(url):
    options = {"ajax_wait": "true", "page_wait": 3000}
    response = api.get(url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Failed to fetch the page. Status: {response['status_code']}")
    return None

if __name__ == "__main__":
    area_url = "https://www.just-eat.co.uk/area/ec4r3tn"
    html = fetch_listings(area_url)
    print(html[:500] if html else "No HTML returned")

Die beiden Wartoptionen sind wichtig für ein Raster, das sich nach dem Laden füllt. ajax_wait weist die API an, auf den Abschluss des asynchronen Inhalts zu warten, und page_wait hält für eine feste Anzahl von Millisekunden, sodass die spät gerenderten Karten erscheinen, bevor die Seite erfasst wird. Führen Sie das Skript aus, und Sie sollten echtes Listen-Markup sehen, keine leere Hülle und keine Challenge-Seite. Das bestätigt, dass das Rendern funktioniert, bevor Sie einen einzigen Selektor schreiben.

Crawlbase Crawling API

Dieses Gebietsraster füllt sich erst, sobald das JavaScript läuft, und Just Eat blockiert Traffic, der nicht wie ein echter Browser aussieht. Die Crawling API nimmt Ihr Token, führt die Seite in einem echten Browser aus, rotiert serverseitig durch Residential-IPs und übernimmt das Lösen der CAPTCHAs, dann übergibt sie Ihnen fertiges HTML. Sie sparen sich den Betrieb einer Flotte von Headless-Browsern und eines Proxy-Pools. Richten Sie sie zunächst auf der kostenlosen Stufe mit bis zu 20.000 Anfragen auf eine Gebietsseite.

Schritt 2: Die Restaurant-Karten mit BeautifulSoup parsen

Mit dem gerenderten HTML in der Hand laden Sie es in BeautifulSoup, finden jede Restaurant-Karte und ziehen jedes Feld über seinen data-qa-Selektor heraus. Jede Karte trägt den Namen, die Küche und die Bewertung sowie einen Anker, dessen relatives href Sie an die Basis-URL der Seite anfügen. Ein kleiner text_of-Helfer gibt eine leere Zeichenkette zurück, wenn ein Feld fehlt, statt bei einem .text-Aufruf auf nichts einen Fehler zu werfen.

python
from bs4 import BeautifulSoup

BASE = "https://www.just-eat.co.uk"

def text_of(card, selector):
    el = card.select_one(selector)
    return el.get_text(strip=True) if el else ""

def parse_restaurants(html):
    soup = BeautifulSoup(html, "html.parser")
    restaurants = []
    cards = soup.select('div[data-qa="restaurant-card"]')
    for card in cards:
        try:
            anchor = card.select_one("a[href]")
            link = BASE + anchor["href"] if anchor else ""
            restaurants.append({
                "name": text_of(card, 'div[data-qa="restaurant-info-name"]'),
                "cuisine": text_of(card, 'div[data-qa="restaurant-cuisine"]'),
                "rating": text_of(card, 'div[data-qa="restaurant-ratings"]'),
                "link": link,
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return restaurants

Der Selektor data-qa="restaurant-card" findet die Listencontainer, und select_one liest jedes Feld innerhalb einer Karte. Das Bewertungsfeld kommt als kombinierte Zeichenkette wie "4.5(26)" durch, die Sternwertung gefolgt von der Anzahl der Rezensionen in Klammern; behalten Sie es hier roh und teilen Sie es weiter unten auf, falls Sie die beiden Werte getrennt brauchen. Der Link ist auf der Seite relativ, daher gibt Ihnen das Voranstellen von BASE eine absolute URL, der Sie direkt zur Speisekarte folgen können. Jede Karte in ein try/except zu hüllen bedeutet, dass ein fehlerhafter Eintrag nicht den gesamten Lauf zum Absturz bringt.

Selektoren verschieben sich

Die data-qa-Attribute von Just Eat sind für die eigenen Tests der Seite gedacht, was sie stabiler macht als generierte Klassennamen, aber sie sind kein Vertrag. Behandeln Sie die obigen Selektoren als Ausgangsvorlage. Wenn ein Feld für jede Karte leer zurückkommt, inspizieren Sie die Live-Gebietsseite erneut in den Entwicklertools Ihres Browsers und aktualisieren Sie den Selektor. Regelmäßige Selektorpflege ist für jeden produktiven Scraper normal.

Schritt 3: Scrollbasierte Paginierung handhaben

Just Eat paginiert nicht mit nummerierten Seiten. Es verwendet Infinite Scroll: Mehr Restaurants laden, während Sie nach unten scrollen. Die Crawling API kann dieses Scrollen für Sie übernehmen, sodass Sie es nicht manuell verwalten müssen. Tauschen Sie die Wartoptionen gegen scroll und ein scroll_interval aus, das der API mitteilt, wie viele Sekunden sie weiterscrollen und laden soll, bevor sie die Seite erfasst. Sie brauchen page_wait nicht daneben; das Scroll-Intervall deckt das Warten ab.

python
def fetch_listings(url):
    options = {"scroll": "true", "scroll_interval": "20"}
    response = api.get(url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Failed to fetch the page. Status: {response['status_code']}")
    return None

Hier ist scroll_interval auf 20 gesetzt, sodass die API 20 Sekunden lang scrollt, bevor sie erfasst, lang genug, um die meisten Restaurants in einem belebten Gebiet zu laden. Erhöhen Sie es für dichtere Gebiete und senken Sie es für ruhige; längeres Scrollen kostet mehr Zeit pro Anfrage, also passen Sie es an die Seite an. Damit sieht parse_restaurants das vollständige Raster statt nur des ersten Bildschirms.

Schritt 4: Das Listenskript zusammensetzen und JSON und CSV exportieren

Verdrahten Sie nun das Abrufen und das Parsen zu einem lauffähigen Skript und schreiben Sie dann die Datensätze sowohl nach JSON als auch nach CSV, sodass Sie sie in ein Notebook oder eine Tabellenkalkulation laden können. Eine gemeinsame FIELDS-Liste hält die CSV-Spaltenreihenfolge im Einklang mit den Dictionary-Schlüsseln, sodass die beiden Exporte nie auseinanderdriften.

python
import csv
import json
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})
BASE = "https://www.just-eat.co.uk"
FIELDS = ["name", "cuisine", "rating", "link"]

def fetch_listings(url):
    options = {"scroll": "true", "scroll_interval": "20"}
    response = api.get(url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Failed to fetch the page. Status: {response['status_code']}")
    return None

def text_of(card, selector):
    el = card.select_one(selector)
    return el.get_text(strip=True) if el else ""

def parse_restaurants(html):
    soup = BeautifulSoup(html, "html.parser")
    restaurants = []
    cards = soup.select('div[data-qa="restaurant-card"]')
    for card in cards:
        try:
            anchor = card.select_one("a[href]")
            link = BASE + anchor["href"] if anchor else ""
            restaurants.append({
                "name": text_of(card, 'div[data-qa="restaurant-info-name"]'),
                "cuisine": text_of(card, 'div[data-qa="restaurant-cuisine"]'),
                "rating": text_of(card, 'div[data-qa="restaurant-ratings"]'),
                "link": link,
            })
        except Exception as e:
            print(f"Skipped a card: {e}")
    return restaurants

def export(rows, name="just_eat_restaurants"):
    with open(f"{name}.json", "w", encoding="utf-8") as f:
        json.dump(rows, f, indent=4, ensure_ascii=False)
    with open(f"{name}.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=FIELDS)
        writer.writeheader()
        writer.writerows(rows)
    print(f"Saved {len(rows)} restaurants to {name}.json and {name}.csv")

def main():
    url = "https://www.just-eat.co.uk/area/ec4r3tn"
    html = fetch_listings(url)
    if not html:
        return
    rows = parse_restaurants(html)
    export(rows)

if __name__ == "__main__":
    main()

Führen Sie das vollständige Skript mit python just_eat_scraper.py aus. Es ruft die gerenderte, gescrollte Gebietsseite ab, parst eine Zeile pro Restaurant und schreibt sowohl just_eat_restaurants.json als auch just_eat_restaurants.csv. Das Feld link in jeder Zeile ist genau die URL, die Sie im nächsten Abschnitt in den Menü-Scraper einspeisen.

Wie die Listenausgabe aussieht

Sie erhalten eine saubere Liste von Restaurant-Datensätzen, in Listenreihenfolge, bereit zum Schreiben nach JSON, CSV oder in eine Datenbank.

json
[
  {
    "name": "Tower Mangal",
    "cuisine": "Turkish, Mediterranean",
    "rating": "4.5(26)",
    "link": "https://www.just-eat.co.uk/restaurants-tower-mangal-southwark/menu"
  },
  {
    "name": "Sud Italia",
    "cuisine": "Pizza, Italian",
    "rating": "3(2)",
    "link": "https://www.just-eat.co.uk/restaurants-sud-italia-aldgate/menu"
  }
]

Schritt 5: Die Speisekarte eines Restaurants scrapen

Der Listen-Link zeigt direkt auf die Menüseite eines Restaurants, die den tieferen Detailgrad enthält: die Gerichte, ihre Preise und ihre Beschreibungen, gruppiert nach Kategorie. Die Menüseite ist ebenfalls JavaScript-gerendert und scroll-paginiert, sodass die Abruflogik die Listen-Abruflogik widerspiegelt. Inspizieren Sie eine Menüseite auf dieselbe Weise, und Sie finden diese Elemente:

  • Kategorie: ein <section> mit data-qa="item-category"; ihr Name lebt im <h2> mit data-qa="heading".
  • Gerichtsname: im <h2> des Eintrags mit data-qa="heading".
  • Gerichtspreis: in einem <span>, dessen Klasse mit formatted-currency-style beginnt.
  • Gerichtsbeschreibung: in einem <div>, dessen Klasse mit new-item-style_item-description beginnt.

Da die Preis- und Beschreibungsklassen mit einem stabilen Präfix generiert werden, gleicht der Parser über das Präfix mit dem Attributselektor [class^="..."] ab statt über den vollständigen, volatilen Klassennamen. Ein kleiner re.sub-Aufruf fasst die Folgen von Leerraum zusammen, die Just Eat in langen Beschreibungen hinterlässt.

python
import csv
import json
import re
from crawlbase import CrawlingAPI
from bs4 import BeautifulSoup

api = CrawlingAPI({"token": "YOUR_CRAWLBASE_TOKEN"})
MENU_FIELDS = ["category", "name", "price", "description"]

def fetch_menu_page(url):
    options = {"scroll": "true", "scroll_interval": "15"}
    response = api.get(url, options)
    if response["status_code"] == 200:
        return response["body"].decode("utf-8")
    print(f"Failed to fetch the menu page. Status: {response['status_code']}")
    return None

def text_of(node, selector, default=""):
    el = node.select_one(selector)
    return el.get_text(strip=True) if el else default

def parse_menu(html):
    soup = BeautifulSoup(html, "html.parser")
    menu = []
    categories = soup.select('section[data-qa="item-category"]')
    for category in categories:
        category_name = text_of(category, 'h2[data-qa="heading"]', "Uncategorized")
        items = category.select('div[data-qa="item-category-list"] div[data-qa="item"]')
        for item in items:
            description = text_of(item, 'div[class^="new-item-style_item-description"]')
            menu.append({
                "category": category_name,
                "name": text_of(item, 'h2[data-qa="heading"]'),
                "price": text_of(item, 'span[class^="formatted-currency-style"]'),
                "description": re.sub(r"\s+", " ", description),
            })
    return menu

def export_menu(rows, name="just_eat_menu"):
    with open(f"{name}.json", "w", encoding="utf-8") as f:
        json.dump(rows, f, indent=4, ensure_ascii=False)
    with open(f"{name}.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=MENU_FIELDS)
        writer.writeheader()
        writer.writerows(rows)
    print(f"Saved {len(rows)} menu items to {name}.json and {name}.csv")

def main():
    menu_url = "https://www.just-eat.co.uk/restaurants-tower-mangal-southwark/menu"
    html = fetch_menu_page(menu_url)
    if not html:
        return
    rows = parse_menu(html)
    export_menu(rows)

if __name__ == "__main__":
    main()

Die Menüseite scrollt ebenfalls, daher verwendet fetch_menu_page dieselbe scroll-Option mit einem kürzeren scroll_interval von 15 Sekunden, da die meisten Speisekarten kleiner sind als das Restaurantraster eines belebten Gebiets. parse_menu durchläuft jeden data-qa="item-category"-Abschnitt, liest die Kategorieüberschrift einmal, durchläuft dann die Einträge darin und erfasst den Gerichtsnamen, den Preis und die bereinigte Beschreibung. Um breiter zu gehen, speisen Sie ihm die link-Werte aus Ihrem Listenexport ein und takten Sie die Anfragen mit einer kurzen Verzögerung zwischen den Restaurants, genauso wie Sie es über Gebietsseiten hinweg tun würden.

Wie die Menüausgabe aussieht

Jeder Menüpunkt wird zu einem flachen Datensatz, der mit seiner Kategorie versehen ist, sodass der Export sauber in eine Tabellenkalkulation oder eine Preisvergleichs-Pipeline lädt.

json
[
  {
    "category": "What's New?",
    "name": "Terry's Chocolate Orange Pie",
    "price": "£2.49",
    "description": "Crispy chocolate pastry filled with a chocolate orange ganache."
  },
  {
    "category": "What's New?",
    "name": "Large Grimace Shake",
    "price": "£3.99",
    "description": "Milkshake base blended with blueberry-flavour syrup."
  }
]

Über Gebiete hinweg skalieren und ungesperrt bleiben

Eine Gebietsseite ist eine Demo; ein echter Recherchejob läuft über viele Postleitzahlen und bohrt sich dann in die Speisekarte jedes Restaurants. Just Eat stellt für jede Postleitzahl eine Gebietsseite unter ihrer eigenen /area/-URL bereit, also halten Sie eine Liste von Postleitzahlen, scrapen jedes Gebiet und folgen dann dem link jedes Restaurants in den Menü-Scraper. Ein paar Gewohnheiten halten diesen breiteren Lauf gesund, und sie gelten für jedes harte kommerzielle Ziel.

  • Takten Sie Ihre Anfragen. Legen Sie eine Verzögerung zwischen Gebietsseiten und zwischen Menüabrufen ein, statt alles auf einmal abzufeuern. Planen Sie schwerere Jobs in den Nebenzeiten, um die Server der Seite zu entlasten.
  • Setzen Sie auf Rotation. Ein Pool aus Residential-IPs verteilt Anfragen über viele Adressen echter Nutzer, sodass keine einzelne ein Ratenlimit auslöst. Die Crawling API übernimmt das für Sie; wenn Sie Ihren eigenen Stack bauen, ist das der Teil, den Sie richtig hinbekommen müssen.
  • Stimmen Sie das Scrollen ab. Setzen Sie scroll_interval so, dass es zur Dichte jeder Seite passt, sodass Sie jede Karte laden, ohne für leerlaufendes Scrollen auf einer kurzen Liste zu zahlen.
  • Behalten Sie nur, was Sie brauchen. Speichern Sie die Listen- und Menüfelder, die Ihr Projekt verwendet, und verwerfen Sie den Rest. Prüfen Sie Ihre data-qa-Selektoren regelmäßig erneut, damit der Scraper mit Markup-Änderungen Schritt hält.

Für das umfassendere Playbook zum Vermeiden von Sperren siehe how to scrape websites without getting blocked, und für mehr dazu, warum das Rendern hier zählt, how to crawl JavaScript websites. Wenn Sie frisch zum Python-Scraping kommen, deckt scrape a website with Python die Grundlagen ab, und um Menüpreise in einen Vergleichsfeed zu verwandeln, zeigt web scraping for price intelligence, wohin diese Daten führen.

Ob das Scrapen von Just Eat erlaubt ist, hängt von den Allgemeinen Geschäftsbedingungen von Just Eat, Ihrer Rechtsordnung und davon ab, was Sie mit den Daten tun. Die Bedingungen von Just Eat beschränken den automatisierten Zugriff, sodass Scraping gegen diese Bedingungen verstoßen kann, egal wie sorgfältig Ihr Tooling ist. Nichts vom Code hier ändert das; er bringt nur den technischen Teil zum Laufen. Lesen Sie die Allgemeinen Geschäftsbedingungen von Just Eat und seine robots.txt und behandeln Sie beide als Grenze für das, was Sie erfassen. Für kommerzielle oder wettbewerbliche Nutzung wird das rechtliche Bild komplexer, und einen Rechtsexperten zu Ihrem konkreten Fall zu konsultieren ist der vernünftige Schritt.

Ein paar Leitlinien, an denen es sich festzuhalten lohnt. Erfassen Sie nur öffentliche Daten: die Restaurantnamen, Küchen, Bewertungen, Listenlinks und Menüpunkte, die jeder auf einer Gebiets- oder Menüseite ohne Konto sehen kann. Halten Sie Ihr Anfragevolumen niedrig genug, dass Sie die Server von Just Eat nicht belasten, und vermeiden Sie personenbezogene Daten, einschließlich allem, was mit identifizierbaren Kunden, Rezensenten oder benannten Einzelpersonen verbunden ist, über das hinaus, was öffentlich gelistet ist. Die Gerichtsbeschreibungen und Fotos auf einer Speisekarte sind die eigenen urheberrechtlich geschützten Inhalte des Restaurants, also veröffentlichen Sie sie nicht pauschal erneut, als wären sie Ihre.

Diese Anleitung ist bewusst auf öffentliche Gebiets- und Menüseiten beschränkt, weil das die Linie ist, die die Arbeit verteidigbar hält. Sie deckt nichts ab, was hinter einer Anmeldung, einem Konto- oder Bestellverlauf, Zahlungsdetails oder einem Versuch liegt, eine Authentifizierung oder ein CAPTCHA zu umgehen, das zu bestehen Sie nicht berechtigt sind. Wenn Ihr Projekt mehr als öffentliche Listendaten braucht, oder garantierte Struktur und kommerzielle Rechte, dann ist eine offizielle Partnerschaft oder eine Datenvereinbarung mit Just Eat der richtige Weg, nicht ein cleverer Scraper.

Zusammenfassung

Wichtigste Erkenntnisse

  • Just-Eat-Gebietsseiten sind ein öffentlicher Restaurantkatalog. Jede /area/-Seite listet, wer in einer Postleitzahl liefert, mit Name, Küche, Bewertung und einem Link, weshalb sie für die lokale Lebensmittelmarktforschung nützlich ist.
  • Sie brauchen Rendering und eine vertrauenswürdige IP zusammen. Just Eat füllt sein Raster clientseitig und blockiert Bot-Traffic, sodass die Crawling API die Seite in einem Aufruf hinter einer Residential-IP rendert.
  • Setzen Sie auf die data-qa-Selektoren. Durchlaufen Sie für Listen data-qa="restaurant-card"-Karten und für Speisekarten data-qa="item-category"-Abschnitte; diese Testattribute sind robuster als generierte Klassennamen, verschieben sich aber dennoch.
  • Treiben Sie Infinite Scroll mit der API an. Übergeben Sie scroll und scroll_interval, statt das Scrollen selbst zu verwalten, und stimmen Sie das Intervall darauf ab, wie dicht jede Seite ist.
  • Bleiben Sie bei öffentlichen Daten. Respektieren Sie die Bedingungen und die robots.txt von Just Eat, vermeiden Sie Konten, Bestellungen und persönliche Informationen, und veröffentlichen Sie urheberrechtlich geschützte Menüinhalte nicht als Ihre eigenen.

Häufig gestellte Fragen

Warum gibt eine einfache Anfrage keine Restaurants von Just Eat zurück?

Just Eat rendert sein Restaurantraster clientseitig und lädt mehr Karten, während Sie scrollen, sodass eine rohe Anfrage oft eine leere Hülle erhält. Obendrein fordert die Seite Traffic heraus oder blockiert ihn, der nicht wie ein echter Browser aussieht. Die Seite über die Crawling API hinter einer vertrauenswürdigen IP zu rendern, mit aktivierter Scroll-Option, löst beides, weshalb der Scraper hier seine Anfrage darüber leitet.

Wie scrape ich Just Eat für ein bestimmtes Gebiet?

Jedes Just-Eat-Gebiet hat seine eigene stabile /area/-URL, die auf der Postleitzahl basiert, zum Beispiel /area/ec4r3tn für das Gebiet London Bridge. Richten Sie den Scraper auf die gewünschte Gebiets-URL. Um viele Gebiete abzudecken, halten Sie eine Liste von Postleitzahlen und durchlaufen Sie deren URLs, wobei Sie die Anfragen mit einer kurzen Verzögerung dazwischen takten.

Kann ich Menüinformationen für bestimmte Restaurants extrahieren?

Ja. Das Feld link jedes Eintrags zeigt direkt auf die Menüseite des Restaurants. Speisen Sie diese URL in den Menü-Scraper ein, um den Gerichtsnamen, den Preis und die Beschreibung gruppiert nach Kategorie zu ziehen. Die Menüseite ist JavaScript-gerendert und scroll-paginiert wie die Gebietsseite, sodass dieselbe scroll-Option die vollständige Speisekarte vor dem Parsen lädt.

Wie handhabt der Scraper das Infinite Scroll von Just Eat?

Just Eat verwendet scrollbasierte Paginierung statt nummerierter Seiten. Statt das Scrollen selbst zu automatisieren, übergeben Sie scroll: "true" und ein scroll_interval in Sekunden an die Crawling API, und sie scrollt die Seite serverseitig, bis das Intervall abläuft, und gibt dann das vollständig geladene HTML zurück. Erhöhen Sie das Intervall für dichtere Gebiete und senken Sie es für kurze Speisekarten.

Warum data-qa-Selektoren statt Klassennamen verwenden?

Just Eat liefert generierte Utility-Klassennamen aus, die sich ohne Vorankündigung ändern, während seine data-qa-Attribute für die eigenen automatisierten Tests der Seite existieren und über Releases hinweg stabiler bleiben. Auf data-qa="restaurant-card" oder data-qa="item-category" abzuzielen gibt Ihnen einen robusteren Ansatzpunkt. Für den Preis und die Beschreibung, die generierte Klassen mit einem festen Präfix verwenden, gleicht der Parser über dieses Präfix mit einem [class^="..."]-Selektor ab.

Wie vermeide ich es, beim Scrapen von Just Eat gesperrt zu werden?

Halten Sie Ihre Anfragerate pro IP niedrig, fügen Sie eine Verzögerung zwischen Gebiets- und Menüabrufen ein und leiten Sie über rotierende Residential-IPs, sodass keine einzelne Adresse ein Ratenlimit auslöst. Die Crawling API verwaltet die Rotation, einen vertrauenswürdigen IP-Pool und die CAPTCHA-Handhabung für Sie; wenn Sie Ihren eigenen Stack bauen, ist das der Teil, in den Sie investieren sollten. Beobachten Sie die Statuscodes und drosseln Sie, wenn Sie anfangen, Challenges zu sehen.

Jetzt loslegen

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.

Self-Service · Kein Verkaufsgespräch erforderlich · Enterprise-Crawl-Volumen verfügbar