Anmelden

Drei Fehlerklassen

Jeder Crawlbase-Fehler fällt in einen von drei Buckets, und jeder erfordert eine andere Reaktion.

Transient
retry
Netzwerk-Aussetzer, kurzer Upstream-Ausfall, Rate Limit. 429, 500, 503, 522, 599. Immer mit Backoff erneut versuchen.
Seitenseitig
handle
Die Zielseite hat einen echten Fehler zurückgegeben: 404, 410, 451. Nicht erneut versuchen - die Seite existiert tatsächlich nicht oder ist nicht zugänglich. Markieren Sie die URL als fehlgeschlagen und machen Sie weiter.
Konfiguration
fix code
Ihr Fehler. 401, 402, 403, 422. Erneutes Versuchen hilft nicht - korrigieren Sie den Request, das Token oder den Account.

Produktions-Retry-Muster

Das Muster, das unter Last hält: exponentielles Backoff mit vollem Jitter, begrenzte Versuche und ein Dead-Letter-Ziel für endgültige Fehler.

import time, random, logging
from crawlbase import CrawlingAPI

api = CrawlingAPI({'token': 'YOUR_TOKEN'})
log = logging.getLogger('crawler')

TRANSIENT = {429, 500, 503, 522, 599}
TERMINAL  = {401, 402, 403, 404, 410, 422, 451}

def crawl(url, max_attempts=5, base=0.5, cap=30):
    for attempt in range(max_attempts):
        res = api.get(url)
        status = res['status_code']

        if status == 200 and res['pc_status'] == 200:
            return res

        if status in TERMINAL or res['pc_status'] in TERMINAL:
            log.warning(f'Terminal error {status}/{res['pc_status']} for {url}')
            raise PermanentFailure(url, status)

        # Transient - sleep with full jitter, then retry
        wait = min(cap, base * (2 ** attempt))
        wait = random.uniform(0, wait)
        log.info(f'Attempt {attempt+1} got {status}; sleeping {wait:.2f}s')
        time.sleep(wait)

    raise RuntimeError(f'Exhausted retries for {url}')

class PermanentFailure(Exception): pass
const { CrawlingAPI } = require('crawlbase');
const api = new CrawlingAPI({ token: process.env.CRAWLBASE_TOKEN });

const TRANSIENT = new Set([429, 500, 503, 522, 599]);
const TERMINAL  = new Set([401, 402, 403, 404, 410, 422, 451]);

async function crawl(url, { maxAttempts = 5, base = 500, cap = 30000 } = {}) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const res = await api.get(url);
    const status = res.statusCode;

    if (status === 200 && res.pcStatus === 200) return res;

    if (TERMINAL.has(status) || TERMINAL.has(res.pcStatus)) {
      throw new Error(`Permanent failure \${status} for \${url}`);
    }

    const wait = Math.random() * Math.min(cap, base * 2 ** attempt);
    await new Promise(r => setTimeout(r, wait));
  }
  throw new Error(`Exhausted retries for \${url}`);
}

Dead-Letter-Queue

Wenn Retries erschöpft sind, lassen Sie die URL nicht stillschweigend fallen. Schieben Sie sie an einen Ort, an dem ein Mensch sie überprüfen kann.

  • Für Crawler API-Nutzer: Fehler werden automatisch bis zu Ihrer konfigurierten Anzahl wiederholt und dann mit den Fehler-Metadaten an Ihren Webhook geliefert. Keine DLQ zu bauen.
  • Für Direkt-API-Nutzer: Schreiben Sie bei endgültigem Fehler die URL + Status + letzten Response-Body in eine separate Queue oder Tabelle. Wöchentlich überprüfen.
Nicht ewig retryen

Begrenzen Sie Retries auf etwa 5. Eine URL, die 5 Mal hintereinander fehlschlägt, wird mit ziemlicher Sicherheit auch 50 Mal fehlschlagen. Sparen Sie die Zyklen für neue Arbeit.

Was Sie überwachen sollten

Die vier Signale, die jedes Crawlbase-nutzende System darstellen sollte:

SignalWo es herkommtAlert wenn
Erfolgsratepc_status == 200 / gesamt< 95 % anhaltend für 10 Min
P95-LatenzRequest-Dauer> 15s anhaltend
429-RateHTTP-Statushistogramm> 5% anhaltend - Concurrency erhöhen
Retry-Anzahl-VerteilungIhre Retry-SchleifeP95 > 2 - irgendetwas verschlechtert sich upstream

Taggen Sie jede Metrik mit der Zieldomain, damit Sie erkennen können, wenn eine einzelne Site Ihre Gesamtwerte vergiftet.

Retries sicher machen

Crawlbase-Requests sind von Natur aus idempotent - ein GET auf dieselbe URL mit demselben Token liefert jedes Mal die gleiche Art von Ergebnis. Sie können beliebig oft erneut versuchen, ohne sich um doppelte Seiteneffekte sorgen zu müssen.

Zwei Hinweise:

  • Async + store: Wenn Sie &async=true&store=true verwendet haben, verbraucht jeder Retry ein Credit und erzeugt eine neue rid. Deduplizieren Sie bei Bedarf auf Ihrer Seite.
  • Webhooks: Crawler API-Webhooks können bei Fehlern mehrfach zugestellt werden. Machen Sie Ihren Webhook-Handler idempotent über rid.