logo
languageDEdown
menu

Wie kann man eBay Kleinanzeigen scrapen?

5 Minuten lesen

Als beliebter Online-Marktplatz im deutschsprachigen Raum taucht auf eBay Kleinanzeigen ständig neue Informationen auf – minuteweise kommen unzählige neue Angebote hinzu. Möchte man aus dieser Fülle öffentlich zugänglicher Daten wertvolle Informationen extrahieren, kommt ein eBay Kleinanzeigen Scraper ins Spiel. Was genau ist das eigentlich? Welche Daten lassen sich damit extrahieren? Und welche praktischen Methoden und Vorsichtsmaßnahmen gibt es? Im Folgenden erklären wir Ihnen das ausführlich.

Was ist ein eBay Kleinanzeigen Scraper?

Ein Web-Scraper ist ein Programm (oder ein No-Code-Workflow), das Webseiten automatisiert aufruft, den HTML-Quelltext analysiert und gezielt Informationen extrahiert. Bei eBay Kleinanzeigen bedeutet das konkret:

1. Die Such- oder Kategorie-URL wird per HTTP/HTTPS geladen.

2. Der Scraper identifiziert wiederkehrende HTML-Container (jeder entspricht einer Anzeige).

3. Er holt definierte Felder – z. B. Titel, Preis, PLZ, Bilder-URL – heraus und speichert sie strukturiert (CSV, Excel, Datenbank …).

Wichtig: Es werden nur öffentlich sichtbare Daten gesammelt. Das Umgehen von Logins, Captchas oder das Abgreifen personenbezogener Informationen (Telefonnummern, E-Mails) ist tabu und verstößt gegen AGB und DSGVO.

Welche Daten kann man von eBay Kleinanzeigen scrapen?

Eine Anzeige auf eBay Kleinanzeigen enthält weit mehr Informationen als nur Titel und Preis. Wer die Felder gezielt ausliest, erhält nicht nur Rohdaten, sondern verwertbare Signale zu Produktzustand, Nachfrageniveau und regionalen Marktunterschieden. Die folgende Tabelle zeigt die wichtigsten Datenpunkte, ein konkretes Beispiel und den jeweiligen potenziellen Analyse-Nutzen auf einen Blick.

FeldBeispielNutzen
TitelBosch 
AkkuschrauberGSR 
12V
Produkt- bzw.Modellerkennung
Preis55 € VBPreisanalyse,Verhandlungsspielraum
BeschreibungAkku neu,
Rechnung von 2023
Zustands- undEchtheitsprüfung
KategorieHeimwerken 
>Elektrowerkzeuge
Segmentierung,Wettbewerbsmatrix
Ort / PLZHamburg (22305)Regionale Nachfrage &Preiscluster
Erstelldatum14.07.2025Angebotsdauer,Nachfragetendenz
Profil IDuser_2348761Mehrfachangebotedesselben Verkäufers
Bilder Linkshttps://i.ebayimg.com/images/…Sichtprüfung, Bilder‑KI,CDN‑Download
Aufrufe / Likes152 Views, 3 ❤︎Beliebtheit,Trend‑Früherkennung

Warum überhaupt scrapen? – Use Cases

EBay Kleinanzeigen zählt zu den populärsten Online-Marktplätzen im deutschsprachigen Raum. Im Minutentakt tauchen hier neue Angebote auf – vom günstigen Smartphone bis zum exotischen Ersatzteil. Wer diese Daten systematisch sammelt, kann sich damit einen Marktvorteil verschaffen, indem Trends schneller erkannt, Preise realistischer kalkuliert und neue Geschäftsmodelle bedarfsorientiert aufsetzen werden können. Die wichtigsten Anwendungsfälle lassen sich in sechs Kategorien bündeln:

Marktanalyse: Durchschnitts-, Mindest-, Höchstpreise pro Produkt & Region ermitteln.

Preis-Monitoring: Alarm auslösen, wenn ein Artikel unter Schwellenwert X fällt.

Wettbewerbsbeobachtung: Welche Händlerinnen bieten in „meinem“ PLZ-Gebiet?

Lead-Generierung: Frisch inserierte Schnäppchen sofort erkennen und ankaufen.

Sortiments-Benchmarking: Sortimentsbreite & -tiefe von Mitbewerbern nachvollziehen.

Datenanreicherung: Interne Produktkataloge um Echtbilder, Beschreibungen, Stichwörter ergänzen.

Praxis-Szenario: „IKEA Kallax in Berlin” wöchentlich tracken

Ziel
Ein kleiner Gebrauchtmöbel-Händler möchte wissen, zu welchen Preisen das Regal „IKEA Kallax 4×4“ in Berlin gehandelt wird, um realistische Ankauf- und Verkaufspreise festzulegen.

Rahmen

  • Zeitraum: jeweils die letzten 7 Tage
  • Region: Berlin (PLZ-Bereich 10115 – 14199)
  • KPI: Median-Preis + Mindest-Preis + Anzahl neuer Anzeigen

Ablauf

1. Crawler ruft jeden Freitagabend die Such-URL: https://www.kleinanzeigen.de/s-berlin/kallax/k0l3331
(PLZ-ID 3331 steht für Berlin) ab.

2. Datensätze werden in CSV gespeichert und auf Google Drive abgelegt.

3. In Google Sheets berechnet eine einfache Formel automatisch Median- und Minimal- preis.

4. Ein Bedingtes-Format markiert Inserate 20 % unter Median als potenzielle Ankauf-Kandidaten.

Ergebnis eines echten Laufs (KW 28 / 2025):
142 Inserate → Median 55€, Minimum 20€, 41 Anzeigen ≤ 44€ (= 20 % unter Median). Quelle: Crawl vom 15. 07. 2025.

Wie kann man eBay Kleinanzeigen ohne Codierung scrapen?

Konvertiere Website-Daten direkt in Excel, CSV, Google Sheets und Ihre Datenbank.

Scrape Daten einfach mit Auto-Dedektion, ganz ohne Coding.

Scraping-Vorlagen für beliebte Websites, um Daten mit wenigen Klicks zu erhalten.

Mit IP-Proxys und fortschrittlicher API wird nie blockiert.

Cloud-Dienst zur Planung von Datenabfragen zu jedem gewünschten Zeitpunkt.

Methode 1: Vorgefertigter eBay Kleinanzeigen Scraper (Template)

https://www.octoparse.de/template/kleinanzeigen-scraper-product-details

So funktioniert es in der Praxis: Öffnen Sie zunächst Octoparse und wechseln Sie in das Template Center. Suchen Sie dort nach „Kleinanzeigen Scraper – Product Details“ und wählen Sie die Vorlage aus. Anschließend geben Sie entweder ein Stichwort oder die komplette Listen-URL Ihrer gewünschten eBay-Kleinanzeigen-Suche ein. Aktivieren Sie den Proxy-Pool „Europa West“, um IP-Sperren zu vermeiden, prüfen Sie die Vorschau und starten Sie den Crawl. Während der Ausführung können Sie den Fortschritt live beobachten; danach exportieren Sie die Ergebnisse wahlweise als CSV, Excel, JSON oder rufen sie über die REST-API ab.

Der große Vorteil dieser Vorlage: Sie arbeitet extrem schnell, weil im Backend optimierte Python-Selektoren zum Einsatz kommen, nutzt eine integrierte IP-Rotation inklusive Captcha-Bypass und erfordert praktisch keinen Einrichtungsaufwand – ideal für spontane Ad-hoc-Analysen.

Methode 2: Auto-Detect in Octoparse

Nutzen Sie den Auto-Detect-Modus, wenn die feste Template-Struktur nicht zu Ihrem speziellen Listing passt, wenn Sie zusätzliche Felder wie Lieferoption oder Artikelzustand auslesen müssen oder wenn sich das Seiten-Layout häufiger ändert.

Die Vorgehensweise ist denkbar einfach: Fügen Sie zunächst die gewünschte Such- oder Kategorie-URL in Octoparse ein, klicken Sie auf „Auto-Detect Website Data“ und lassen Sie das Tool automatisch jede Anzeigen-Kachel markieren. Sollten einzelne Felder fehlen, ergänzen Sie sie per Mausklick – etwa die vollständige Beschreibung oder das Thumbnail-Bild. Aktivieren Sie anschließend Infinite-Scroll sowie AJAX-Pagination, damit auch dynamisch nachgeladene Anzeigen erfasst werden. Schalten Sie die Proxy-Rotation ein, speichern Sie den Workflow und starten Sie ihn als Cloud-Run.

Auto-Detect in Octoparse

Der Auto-Detect-Ansatz bietet Ihnen deutlich mehr Flexibilität: Sie können eigene Felder definieren, exotische Kategorien problemlos scannen und UI-Änderungen mit wenigen Klicks nachtrainieren, ohne den gesamten Workflow neu aufzusetzen.

Zusammenfassung: Greifen Sie zum Template, wenn Sie ohne Vorarbeit schnell zahlreiche Standarddaten extrahieren möchten; wählen Sie Auto-Detect, sobald das Layout abweicht oder Sie zusätzliche, individuell definierte Felder benötigen.

Zusammenfassung

Mit Python scrapen

Für Teams mit Entwickler-Know-how kann sich ein eigener Crawler lohnen. Die Vorteile eines eigenen Python-Crawlers liegen in der lückenlosen Kontrolle über jeden einzelnen Request, der Möglichkeit, die extrahierten Daten ohne Zwischenschritte direkt in Ihre Datenbank zu schreiben, und der Freiheit, sämtliche unternehmensspezifischen Regeln, Filter und Nachbearbeitungsschritte exakt nach Ihren Anforderungen umzusetzen.

Python-Code – Zeile für Zeile erklärt

import requests, pandas as pd, time, random
frombs4importBeautifulsoup

Imports:

  • requests für HTTP-Abrufe
  • pandas zum Speichern / Auswerten
  • time & random für Pausen + Proxy-Rotation
  • BeautifulSoup zum HTML-Parsen
PROXIES = [
    "http://34.159.111.0:3128',
"http://88.99.0.0:8080
]
HEADERS = {'User-Agent': 'Mozilla/5.0 (Windows NT10.0;Win64;x64)'}

Konstanten: zwei frei wählbare HTTP-Proxies (Platzhalter) und ein Browser-typischer
User-Agent, damit der Request nicht wie ein Bot aussieht.

deffetch(url):
  proxy={'http':random.choice(PROXIES)}
  r = requests.get(url, headers=HEADERS, proxies=proxy, timeout=10)
  r.raise for_status()              # wirft Exception bei 4xx/5xx
  return r.text

fetch()

  • holt eine Seite ab
  • wählt zufällig einen Proxy
  • bricht bei Fehlern sauber ab (raise_for_status) – wichtig für Retry-Logik
def parse(html):
  soup = Beautifulsoup(html,'html.parser')
  for ad in soup.select('article.aditem'):
      yield {
           'titel': ad.select_one('.text-module-begin').get_text(sttrip=True)
           'preis': ad.select_one('.aditem-main--middle').get_text(strip=True)
           'ort': ad.select_one('.aditem-main--top').get_text(strip=True)
           'url': 'https://www.kleinanzeigen.de' + ad['data-href]
      }

parse()

  • baut einen Soup aus dem HTML
  • iteriert über jeden (eine Anzeige)
  • liest Titel, Preis, Ort, relativen Link aus
  • gibt ein Dict – der Generator spart Speicher
base = "https://www.kleinanzeigen.de/s-berlin/kallax/k013331?seite={}
records = []
for page in range(1,6):     # 5 Seiten ≈ 50 Anzeigen
    html = fetch(base.format(page))
    records.extend(parse(html))
    time.sleep(1.2)         # Fair-Use-Pause (≈ 0,8 RPS)
  • Pagination – die URL hat den Platzhalter ?seite={}
  • es werden fünf Seiten abgegrast (anpassbar)
  • 1,2 s Pause schrumpft die Request-Rate unter 1 Request / Sekunde
df = pd.DataFrame(records)
# Preis bereinigen: alles außer Ziffern entfernen
df['preis_eur'] = (df['preis']
                   .str.replace('[^0-9]', '', regex=True)
                   .astype(int))
  • DataFrame erstellen
  • Text „55 € VB“ → 55 via RegEx
# Kennzahlen berechnen
median = int(df['preis_eur'].median())
minimum = int(df['preis_eur'].min())
print('Median:', median, '€ Minimum:', minimum,'€')
  • schnelle KPI-Berechnung direkt in Python – dieselben Formeln funktionieren auch in Excel / Sheets.
df.to_csv('kallax_berlin.csv', index=False, encoding='utf-8')
print('Fertig -',len(df), 'Datensätze gespeichert')

Export in UTF-8, sofort in Excel oder BI-Tool importierbar.

Möchten Sie mehr Ergebnisse, erhöhen Sie den Seitenbereich zum Beispiel auf range(1, 11) – das liefert rund hundert Inserate. Für eine andere Region tauschen Sie die PLZ-ID aus, etwa von l3331 (Berlin) auf l3332 (Potsdam). Mehrere Suchbegriffe lassen sich über eine Schleife mit verschiedenen Basis-URLs verarbeiten. Soll der Crawl automatisch laufen, legen Sie das Skript auf einem Linux-Server ab und hinterlegen einen Cron-Job über crontab -e. Und wenn Sie die Daten direkt in Ihre Datenbank schreiben möchten, verbinden Sie sich per SQLAlchemy und speichern sie mit df.to_sql(‘tab_kallax’, engine) unmittelbar in der gewünschten Tabelle.

Vollständiges Code-Beispiel

import requests
import pandas as pd
import time
import random
import logging
from datetime import datetime
from bs4 import BeautifulSoup
from retrying import retry  # Benötigt: pip install retrying

# ----------------------------
# Konfiguration & Einstellungen
# ----------------------------
CONFIG = {
    "basis_url": "https://www.kleinanzeigen.de/s-berlin/kallax/k013331?seite={}",
    "anzahl_seiten": 10,  # Mehr Seiten als ursprünglich
    "wartezeit_min": 1.5,  # Dynamischere Wartezeiten
    "wartezeit_max": 2.5,
    "proxies": [
        "http://34.159.111.0:3128",
        "http://88.99.0.0:8080",
        "http://138.197.209.0:8080"  # Zusätzlicher Proxy
    ],
    "user_agents": [  # Rotation von User-Agents
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15",
        "Mozilla/5.0 (X11; Linux x86_64) Firefox/113.0"
    ],
    "ausgabedatei_csv": "kallax_berlin_erweitert.csv",
    "ausgabedatei_json": "kallax_berlin_erweitert.json"
}

# Logging konfigurieren (zur Fehlersuche)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[logging.FileHandler("scraper_log.log"), logging.StreamHandler()]
)
logger = logging.getLogger(__name__)


# ----------------------------
# Funktionen mit Fehlerbehandlung
# ----------------------------
@retry(
    stop_max_attempt_number=3,  # Maximal 3 Versuche bei Fehlern
    wait_exponential_multiplier=1000,  # Wartet 1s, 2s, 4s zwischen Versuchen
    retry_on_exception=lambda e: isinstance(e, (requests.exceptions.RequestException, ConnectionError))
)
def hole_seite(url):
    """
    Lädt eine Webseite mit zufälligem Proxy und User-Agent.
    Mit Retry-Mechanismus bei Netzwerkfehlern.
    """
    proxy = {"http": random.choice(CONFIG["proxies"])}
    user_agent = random.choice(CONFIG["user_agents"])
    headers = {"User-Agent": user_agent, "Accept-Language": "de-DE,de;q=0.9"}

    logger.info(f"Lade Seite: {url} (Proxy: {proxy['http'].split('@')[-1]})")
    antwort = requests.get(
        url,
        headers=headers,
        proxies=proxy,
        timeout=15  # Längerer Timeout für instabile Proxies
    )
    antwort.raise_for_status()  # Fehler bei 4xx/5xx Statuscodes
    logger.debug(f"Seite geladen (Status-Code: {antwort.status_code})")
    return antwort.text


def parse_anzeigen(html_inhalt):
    """
    Parst HTML-Inhalt und extrahiert detaillierte Daten aus Kleinanzeigen.
    Enthält Fehlerbehandlung für fehlende Elemente.
    """
    suppe = BeautifulSoup(html_inhalt, "html.parser")
    anzeigen = suppe.select("article.aditem")  # Selektor für Anzeigencontainer

    if not anzeigen:
        logger.warning("Keine Anzeigen auf der Seite gefunden - evtl. Selektor veraltet?")
        return

    for anzeige in anzeigen:
        # Extrahiere Felder mit Fallback bei fehlenden Elementen
        titel_element = anzeige.select_one(".text-module-begin h2")
        titel = titel_element.get_text(strip=True) if titel_element else "Ohne Titel"

        preis_element = anzeige.select_one(".aditem-main--middle .price")
        preis = preis_element.get_text(strip=True) if preis_element else "Nicht angegeben"

        ort_datum_element = anzeige.select_one(".aditem-main--top .aditem-addon")
        ort_datum = ort_datum_element.get_text(strip=True) if ort_datum_element else "Unbekannt"
        ort, datum = (ort_datum.split("•") if "•" in ort_datum else (ort_datum, "Unbekannt"))

        beschreibung_element = anzeige.select_one(".aditem-main--middle .aditem-description")
        beschreibung = beschreibung_element.get_text(strip=True)[:200] if beschreibung_element else ""  # Kurzfassung

        link_element = anzeige.get("data-href")
        vollstaendiger_link = f"https://www.kleinanzeigen.de{link_element}" if link_element else "Kein Link"

        # Gibt ein Dictionary pro Anzeige zurück
        yield {
            "titel": titel,
            "preis": preis,
            "ort": ort.strip(),
            "erstellungsdatum": datum.strip(),
            "beschreibung_kurz": beschreibung,
            "link": vollstaendiger_link,
            "gescrapet_am": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }


def bereinige_daten(df):
    """
    Bereinigt und transformiert die extrahierten Daten:
    - Preis in numerischen Wert umwandeln
    - Datumswerte formatieren
    - Duplikate entfernen
    """
    logger.info("Bereinige Daten...")

    # Preis bereinigen (entferne Währungszeichen, "VB" etc.)
    df["preis_eur"] = df["preis"].str.extract(r"(\d+,\d+|\d+)").replace(",", ".", regex=True)
    df["preis_eur"] = pd.to_numeric(df["preis_eur"], errors="coerce")  # Ungültige Werte zu NaN

    # "VB" (Verhandlungsbasis) markieren
    df["ist_verhandelbar"] = df["preis"].str.contains("VB", case=False, na=False)

    # Erstelldatum formatieren
    df["erstellungsdatum_aufbereitet"] = pd.to_datetime(
        df["erstellungsdatum"],
        format="%d.%m.%Y",
        errors="coerce"
    )

    # Duplikate entfernen (basierend auf Link)
    df = df.drop_duplicates(subset=["link"], keep="first")
    logger.info(f"Nach Bereinigung: {len(df)} eindeutige Anzeigen")
    return df


def haupt_prozess():
    """Hauptfunktion: Koordiniert Scraping, Parsing und Datenaufbereitung"""
    logger.info("Starte eBay Kleinanzeigen Scraper...")
    datensaetze = []

    try:
        # Durch Seiten iterieren (Pagination)
        for seite in range(1, CONFIG["anzahl_seiten"] + 1):
            url = CONFIG["basis_url"].format(seite)
            try:
                html = hole_seite(url)
                anzeigen_daten = list(parse_anzeigen(html))
                datensaetze.extend(anzeigen_daten)
                logger.info(f"Seite {seite} verarbeitet ({len(anzeigen_daten)} Anzeigen)")
            except Exception as e:
                logger.error(f"Fehler bei Seite {seite}: {str(e)}", exc_info=True)
                continue  # Nächste Seite versuchen

            # Zufällige Wartezeit (um Anti-Bot-Maßnahmen zu umgehen)
            wartezeit = random.uniform(CONFIG["wartezeit_min"], CONFIG["wartezeit_max"])
            time.sleep(wartezeit)

        # Datenaufbereitung
        if not datensaetze:
            logger.warning("Keine Daten gesammelt - Scraping abgebrochen")
            return

        df = pd.DataFrame(datensaetze)
        df_bereinigt = bereinige_daten(df)

        # Statistische Auswertung
        statistik = {
            "durchschnittspreis": df_bereinigt["preis_eur"].mean().round(2),
            "medianpreis": df_bereinigt["preis_eur"].median(),
            "anzahl_verhandelbar": df_bereinigt["ist_verhandelbar"].sum(),
            "anzahl_total": len(df_bereinigt)
        }
        logger.info(f"Statistik: {statistik}")

        # Speichern der Daten
        df_bereinigt.to_csv(CONFIG["ausgabedatei_csv"], index=False, encoding="utf-8-sig")
        df_bereinigt.to_json(CONFIG["ausgabedatei_json"], orient="records", force_ascii=False)
        logger.info(f"Daten gespeichert in {CONFIG['ausgabedatei_csv']} und {CONFIG['ausgabedatei_json']}")

    except KeyboardInterrupt:
        logger.info("Scraper manuell gestoppt")
    except Exception as e:
        logger.critical(f"Kritischer Fehler im Hauptprozess: {str(e)}", exc_info=True)


if __name__ == "__main__":
    haupt_prozess()

Zusammenfassung – kompletter Workflow in 4 Punkter

1. Praxisnutzen
Egal ob Sie das Octoparse-Template, den Auto-Detect-Workflow oder einen kompakten Python-Crawler einsetzen: Bereits ein Mini-Crawl von 50 – 150 Inseraten pro Woche liefert belastbare Preis- und Nachfragestatistiken.

2. Vorgehensweise
URL eingeben ➜ Crawl starten (Template / Auto-Detect oder fetch → parse → Loop)
➜Daten als CSV oder direkt in Ihre Datenbank exportieren – der Ablauf ist modular und lässt sich mit wenigen Klicks beziehungsweise Code-Zeilen anpassen.

3. Fair-Use-Regeln
Unabhängig von der Methode gilt: ≤ 1 Request / Sekunde, Proxy-Rotation aktivieren, keine personenbezogenen Daten sammeln – so vermeiden Sie Blockaden und bleiben DSGVO-konform.

4. Nächste Schritte
Qualität und Skalierung erhöhen Sie mit Retry-Logik (Back-off), Headless-Browsern für endlos scrollende Listen sowie automatischen Reports / BI-Dashboards.

Rechtliche Best Practices

Für einen rechtssicheren Crawl gilt: Erfassen Sie ausschließlich öffentlich zugängliche Daten und lassen Sie jegliche Login-Bereiche außen vor. Prüfen und respektieren Sie die AGB sowie die robots.txt von eBay Kleinanzeigen. Drosseln Sie Ihre Abrufrate auf weniger als eine Anfrage pro Sekunde, speichern Sie keine personenbezogenen Angaben wie Telefonnummern oder E-Mail-Adressen und richten Sie Löschroutinen plus eine klar erkennbare Abuse-Kontaktadresse ein, falls sich jemand über die Datennutzung beschweren möchte.

Fazit

Wenn Sie die beschriebenen Workflows selbst ausprobieren möchten, können Sie Octoparse in einer 14-tägigen Testphase kostenfrei nutzen. Legen Sie einfach einen Account an, wählen Sie das Kleinanzeigen-Template aus und starten Sie Ihren ersten Crawl – ganz ohne Zahlungs- oder Kreditkartendaten. So sehen Sie in wenigen Minuten, ob der Ansatz zu Ihrem Anwendungsfall passt. Viel Spaß beim selbst probieren!

Wenn Sie Probleme bei der Datenextraktion haben, kontaktieren Sie bitte uns per E-Mail (support@octoparse.com). 💬




Erhalte Webdaten in Klicks
Daten-Scraping von jeder Website ganz ohne Codierung.
Kostenloser Download

Beliebte Beiträge

Themen untersuchen

Starten mit Octoparse heute

Downloaden

Verwandte Artikel