Zum Inhalt springen
Zurück zum Blog

Web-Scraping mit Go: Einen zuverlässigen HTML-Scraper erstellen

Sorin-Gabriel MaricaZuletzt aktualisiert am 13 min read
Web-Scraping mit Go: Einen zuverlässigen HTML-Scraper erstellen
TL;DR: Für Web-Scraping mit Go verwenden Sie net/http , um statisches HTML abzurufen, und `gquery`, um Felder mit CSS-Selektoren zu extrahieren. Beginnen Sie mit einer Seite, validieren Sie jeden Datensatz und exportieren Sie JSON. Fügen Sie „Colly“ für die Crawling-Planung oder einen Browser für JavaScript hinzu, sofern Ihr Ziel dies erfordert. Das vollständige Beispiel unten umfasst Timeouts, Antwortbeschränkungen, Statusprüfungen und explizite Parsing-Fehler.

Ein Scraper, der einmalig einen Titel ausgibt, lässt sich leicht demonstrieren. Ein Scraper, der dir mitteilt, wenn sich eine Seite ändert, eine Anfrage fehlschlägt oder ein Feld verschwindet, ist in einer Go-Anwendung jedoch weitaus nützlicher. Der Unterschied ergibt sich aus den Grenzen, die du beim Abrufen, Parsen und Exportieren von Daten setzt.

Dieser Leitfaden führt Sie anhand einer Beispiel-Buchhandlung durch das Web-Scraping mit Go. Sie werden ein Modul erstellen, eine Katalogseite abrufen, Buchdatensätze extrahieren und eine JSON-Datei schreiben. Das Programm ist vollständig, sodass Sie es ausführen können, bevor Sie die Selektoren an eine andere Quelle anpassen. Sie sollten bereits mit Go-Funktionen, Structs, Fehlerrückgaben und grundlegenden Befehlszeilenoperationen vertraut sein.

Der gleiche Ansatz gilt für viele Web-Scraping-Projekte in Go: Definieren Sie zunächst die Ausgabefelder, untersuchen Sie den Quell-HTML-Code und machen Sie fehlende Daten erkennbar. Anschließend werden wir uns mit Paginierung, Colly, Browser-Rendering und Tests befassen, damit Sie die erste Version erweitern können, ohne die Kontrolle über ihr Verhalten zu verlieren.

Halten Sie das anfängliche Erfolgskriterium konkret: Eine angeforderte Seite liefert einen gültigen Satz von Buchdatensätzen oder einen Fehler, der erklärt, warum dies nicht möglich war. So haben Sie einen nützlichen Maßstab, bevor Sie weitere Seiten oder Worker hinzufügen.

Web-Scraping mit Go: Wähle das richtige Werkzeug

Beginnen Sie damit, das Abrufen der Seite, das Parsen des HTML-Codes und die Ausführung im Browser voneinander zu trennen. Es handelt sich um unterschiedliche Aufgaben, auch wenn eine Bibliothek mehrere davon bündelt. Für eine Seite, deren HTML-Antwort bereits die gewünschten Datensätze enthält, reichen ein HTTP-Client und ein Parser aus.

Tool

Aufgabe

Ein nützlicher Ausgangspunkt

net/http

Anfragen senden und Antworten auslesen

Sie möchten explizite Kontrolle über Anfragen und Fehler

goquery

HTML-Elemente auswählen und auslesen

Sie benötigen CSS-Selektoren für heruntergeladene Inhalte

Colly

Anfragen und Callbacks koordinieren

Sie benötigen Navigationsregeln und einen Crawling-Zeitplan

chromedp

Steuerung eines Browsers über CDP

Die Seite erfordert die Ausführung von JavaScript oder eine Interaktion

Das folgende Beispiel kombiniert net/http mit goquery. Dadurch bleiben die Funktionen zum Abrufen und Parsen klein genug, um separat getestet zu werden. Eine Änderung an einem Selektor erfordert keinen Netzwerkaufruf zur Überprüfung, und ein HTTP-Fehler verschwindet nicht im Extraktionscode.

Verwenden Sie Colly, wenn der Zeitaufwand für die Planung erheblich wird. Greifen Sie auf einen Browser zurück, nachdem Sie die Antwort überprüft und sich vergewissert haben, dass die Felder im ursprünglichen HTML-Code fehlen. Das Ausführen eines Browsers führt nicht automatisch dazu, dass die extrahierten Werte korrekt sind.

Beim Web-Scraping mit Go ist diese Entscheidung in der Regel wichtiger als der Vergleich der Sprachgeschwindigkeit. Wählen Sie das am wenigsten komplizierte Tool, das den Inhalt liefert, den Ihr Parser tatsächlich benötigt, und überprüfen Sie anschließend die resultierenden Datensätze.

Ein reproduzierbares Go-Modul einrichten

Erstellen Sie ein Verzeichnis außerhalb eines bestehenden Go-Moduls und initialisieren Sie ein kleines Projekt:

mkdir go-book-scraper
cd go-book-scraper

go mod init example.com/book-scraper
go get github.com/PuerkitoBio/goquery@v1.13.0

Das Beispiel wurde mit Go 1.26.2 und goquery 1.13.0 getestet. Diese festgelegte goquery-Version gibt in ihren Modulmetadaten Go 1.25.0 als Mindestversion an. Verwenden Sie eine kompatible Toolchain, anstatt die Angaben eines alten Tutorials zur neuesten Go-Version zu übernehmen.

Behalten Sie go.mod und go.sum beim Projekt. Der Leitfaden zur Abhängigkeitsverwaltung von Go erklärt, wie Modul-Anforderungen und Prüfsummen reproduzierbare Builds unterstützen. Aktualisieren Sie Abhängigkeiten bewusst und führen Sie die Parser-Tests nach einer Aktualisierung erneut durch.

Unser Ziel ist „Books to Scrape“, eine fiktive Buchhandlung, die für Scraping-Übungen gedacht ist. Ihr Katalog enthält Produktkarten mit Titel, Preis und Link. Das Beispiel geht von UTF-8-HTML aus und verarbeitet pro Aufruf eine Katalogseite. Dieser bewusst kleine Umfang erleichtert die Überprüfung des Web-Scrapings mit Go, bevor Navigation oder parallele Worker hinzugefügt werden.

Erstellen eines getesteten HTML-zu-JSON-Scrapers

Speichern Sie das folgende vollständige Programm als main.go. Es extrahiert den vollständigen Titel jedes Buches, den angezeigten Preis und die absolute Produkt-URL. Die Preise werden als Quellzeichenfolgen einschließlich des Währungssymbols beibehalten, anstatt bereits im ersten Extraktionsschritt eine numerische Konvertierung vorzunehmen.

Die Selektoren sind spezifisch für diese Übungsseite. Jedes article.product_pod ist ein Datensatzcontainer, h3 a enthält den Buchlink und das Attribut für den vollständigen Titel und .price_color den angezeigten Preis. Lesen Sie die Felder innerhalb jeder Karte aus, damit der Titel eines Buches nicht versehentlich mit dem Preis eines anderen Buches verknüpft wird.

package main

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"

	"github.com/PuerkitoBio/goquery"
)

const maxBody = 2 << 20 // A 2 MiB limit chosen for this tutorial.

type Book struct {
	Title string `json:"title"`
	Price string `json:"price"`
	URL   string `json:"url"`
}

func parseBooks(r io.Reader, base *url.URL) ([]Book, error) {
	doc, err := goquery.NewDocumentFromReader(r)
	if err != nil {
		return nil, fmt.Errorf("parse HTML: %w", err)
	}
	cards := doc.Find("article.product_pod")
	if cards.Length() == 0 {
		return nil, fmt.Errorf("no book cards found")
	}
	books := make([]Book, 0, cards.Length())
	for _, node := range cards.Nodes {
		card := goquery.NewDocumentFromNode(node)
		link := card.Find("h3 a").First()
		title, _ := link.Attr("title")
		href, _ := link.Attr("href")
		price := strings.TrimSpace(card.Find(".price_color").Text())
		title = strings.TrimSpace(title)
		href = strings.TrimSpace(href)
		if title == "" || href == "" || price == "" {
			return nil, fmt.Errorf("book card has a missing required field")
		}
		target, err := base.Parse(href)
		if err != nil || (target.Scheme != "http" && target.Scheme != "https") {
			return nil, fmt.Errorf("book card has an invalid link")
		}
		books = append(books, Book{Title: title, Price: price, URL: target.String()})
	}
	return books, nil
}

func fetchBooks(ctx context.Context, client *http.Client, target string) ([]Book, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, target, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", "GoBookTutorial/1.0")
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("fetch page: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected HTTP status: %s", resp.Status)
	}
	body, err := io.ReadAll(io.LimitReader(resp.Body, maxBody+1))
	if err != nil {
		return nil, fmt.Errorf("read body: %w", err)
	}
	if len(body) > maxBody {
		return nil, fmt.Errorf("response exceeds 2 MiB")
	}
	return parseBooks(bytes.NewReader(body), resp.Request.URL)
}

func run(w io.Writer, target string) error {
	client := &http.Client{Timeout: 15 * time.Second}
	defer client.CloseIdleConnections()
	books, err := fetchBooks(context.Background(), client, target)
	if err != nil {
		return err
	}
	encoder := json.NewEncoder(w)
	encoder.SetIndent("", "  ")
	return encoder.Encode(books)
}

func main() {
	target := "https://books.toscrape.com/"
	if len(os.Args) > 1 {
		target = os.Args[1]
	}
	if err := run(os.Stdout, target); err != nil {
		log.Fatal(err)
	}
}

Führen Sie das Programm aus und schreiben Sie die JSON-Ausgabe erst nach erfolgreicher Extraktion:

go run . > books.tmp.json && mv books.tmp.json books.json

Auf der markierten ersten Seite war der erste Datensatz „A Light in the Attic“ mit einem angezeigten Preis von „51,77 £“ und einer absoluten Produkt-URL. Überprüfen Sie diese drei Felder in Ihrer Ausgabe, bevor Sie das Beispiel anpassen. Eine lesbare JSON-Datei allein beweist nicht, dass die Selektoren die beabsichtigten Werte erfasst haben.

Die temporäre Ausgabedatei verhindert, dass Ihr letzter erfolgreicher Datensatz durch eine leere Datei ersetzt wird, falls die nächste Anfrage fehlschlägt. Die Standardausgabe enthält das JSON-Dokument; Fehler werden an die Standardfehlerausgabe weitergeleitet und erzeugen einen Exit-Status ungleich Null.

Der HTTP-Client hat ein Timeout von 15 Sekunden. Die `fetch`-Funktion begrenzt die Antwort zudem auf 2 MiB – dies ist eine für dieses Tutorial gewählte Grenze und keine allgemeine Empfehlung für die Seitengröße. Sie liest ein zusätzliches Byte ein, sodass ein übergroßes Dokument zu einem expliziten Fehler wird, anstatt stillschweigend zu einem abgeschnittenen HTML-Dokument zu werden.

Der Kontext der Anfrage wird an den Client weitergegeben. In einem größeren Programm sollten Sie context.Background() an der Aufrufgrenze durch den Kontext des Jobs, damit durch eine Abbruchaktion laufende Vorgänge gestoppt werden können. Die Go-HTTP-Dokumentation macht zudem eine wichtige Unterscheidung: Eine Antwort wie 404 kann ohne Transportfehler eintreffen. Deshalb erfolgt die Statusprüfung getrennt von err.

Das Parsen gibt einen Fehler zurück, wenn die erwartete Kartenstruktur oder ein Pflichtfeld fehlt. In diesem Beispiel wird die Seite abgelehnt, anstatt ein teilweise ausgefülltes Ergebnis zu erzeugen. Das ist eine Richtlinienentscheidung, die Sie später ändern können, tun Sie dies jedoch explizit: Zeichnen Sie abgelehnte Zeilen auf, falls Ihre Produktionspipeline Teilausgaben akzeptiert.

Schließlich werden Produktlinks anhand der endgültigen Antwort-URL aufgelöst. Dies ist wichtig, wenn eine Seite umleitet oder relative Links verwendet. Der Code validiert Link-Schemas vor dem Export; er folgt diesen Produkt-URLs nicht.

Für das Web-Scraping mit Go bieten diese Grenzen eine nützliche Grundlage: Anfragefehler, Begrenzungen der Seitengröße, Selektorfehler und Ausgabefehler bleiben sichtbar. Die resultierenden Datensätze müssen noch anwendungsspezifischen Prüfungen unterzogen werden, bevor Sie sie als fertigen Datensatz behandeln können.

Paginierung ohne unbegrenztes Crawlen hinzufügen

Das einseitige Programm crawlt nicht den gesamten Buchladen. Um die nächste Katalogseite zu untersuchen, übergeben Sie deren URL explizit:

go run . https://books.toscrape.com/catalogue/page-2.html

Beide Katalogseiten lieferten bei der Überprüfung für dieses Tutorial 20 Datensätze. Dies ist ein auf der Übungswebsite beobachtetes Ergebnis und stellt keine Garantie für zukünftige Seitenlayouts oder andere Websites dar.

Für eine automatische Paginierung sollten Sie die Erkennung als separaten Schritt von der Datensatzextraktion durchführen. Analysieren Sie den Link zur nächsten Seite aus demselben heruntergeladenen Dokument, lösen Sie ihn relativ zur Antwort-URL auf und entscheiden Sie, ob er in den nächsten Anforderungsstapel gehört. Vermeiden Sie es, eine Seite zweimal abzurufen, nur weil Extraktion und Navigation getrennte Funktionen sind.

Eine begrenzte Paginierungsschleife sollte Folgendes tun:

  1. Beginnen Sie mit der genehmigten Katalog-URL und einer Seitenbegrenzung.
  2. Die aktuelle Seite abrufen und validieren.
  3. Extrahieren Sie Datensätze und überprüfen Sie den Link zur nächsten Seite.
  4. Lösen Sie diesen Link auf und stellen Sie sicher, dass das erwartete Schema, der Host und der Pfad übereinstimmen.
  5. Beenden Sie den Vorgang, wenn kein Link zur nächsten Seite vorhanden ist, die Adresse bereits aufgerufen wurde oder das Seitenlimit erreicht ist.
  6. Warten Sie entsprechend den Betriebsgrenzen der Quelle, bevor Sie die nächste Seite anfordern.

Überprüfen Sie sowohl Weiterleitungsziele als auch gefundene Links, wenn ein Crawl auf einer einzigen Quelle bleiben muss. Eine Überprüfung auf dieselbe Quelle allein anhand der ursprünglichen Adresse schränkt nicht ein, wohin eine HTTP-Weiterleitung den Client sendet.

Verfolgen Sie die URLs besuchter Seiten getrennt von den Datensatzkennungen. Eine wiederholt aufgenommene Katalogseite und ein doppelt erfasstes Buch sind unterschiedliche Duplikatsprobleme. Halten Sie beide Prüfungen nachvollziehbar, anstatt alle Abfrageparameter zu löschen und anzunehmen, dass die Adressen gleichwertig werden.

Unser GoSpider-Crawling-Leitfaden behandelt einen speziellen Erkennungs-Workflow. Wenn das Web-Scraping mit Go über bekannte Adressen hinausgeht, hilft Ihnen diese Trennung dabei, festzustellen, ob fehlende Datensätze auf eine unvollständige Erkennung oder eine fehlerhafte Extraktion zurückzuführen sind.

Verwenden Sie Colly, wenn Sie eine Crawling-Planung benötigen

Colly ist nützlich, wenn Sie viele Anfrage-Callbacks, Navigationsregeln und domänenbezogene Limits selbst verwalten. Sein Collector koordiniert den Abruf und Handler wie OnHTML, OnRequest, und OnError.

Verwenden Sie für das v2-Modul den versionierten Modulpfad:

go get github.com/gocolly/colly/v2@v2.3.0

Import github.com/gocolly/colly/v2 in Ihre Go-Quelldatei ein. Das /v2 Suffix ist entscheidend; ein älteres Beispiel, das den nicht versionierten Pfad importiert, wählt diese Modulversion nicht aus. Wenn Sie Colly später zum Demonstrationsprojekt hinzufügen, sollten Sie die Datensatzregeln des Parsers konsistent halten, anstatt gleichzeitig das Ausgabeschema zu ändern.

Konfigurieren AllowedDomains , um Ziele einzuschränken, und verwenden Sie ein LimitRule für die entsprechende Domäne. Überprüfen Sie den von Limit. Legen Sie ein Zeitlimit für die Anfrage fest und registrieren Sie OnError , damit fehlgeschlagene Anfragen nicht hinter Callbacks verschwinden.

Wenn Sie Async, rufen Sie Wait , bevor Sie den Job als abgeschlossen betrachten. Schützen Sie gemeinsam genutzte Slices und Ausgabeschreiber oder übergeben Sie Datensätze über einen Kanal an einen einzigen Schreiber. Ein paralleler Callback, der an ein gemeinsam genutztes Slice anhängt, ist weiterhin paralleler Code und erfordert eine Synchronisationsstrategie.

Collys Paketreferenz dokumentiert diese Steuerelemente. Beachten Sie, dass MaxDepth „bounds“ die Verlinkungstiefe begrenzt; es handelt sich nicht um ein Gesamtseitenbudget. Eine flache Seite kann auf viele Ziele verweisen.

Beim Web-Scraping mit Go kann ein Framework den Code für die Ablaufplanung reduzieren, aber es wählt keine korrekten Selektoren aus, validiert keine geschäftsrelevanten Felder und entscheidet nicht, wie vollständig ein Datensatz sein muss. Halten Sie diese Verantwortlichkeiten explizit fest.

Gehen Sie bewusst mit JavaScript und fehlgeschlagenen Anfragen um

Überprüfen Sie die empfangene Antwort, bevor Sie Ihren Extraktionsstapel ändern. Ein fehlendes Feld kann auf eine Änderung des Selektors, eine andere Antwortseite oder Inhalte hinweisen, die JavaScript noch nicht gerendert hat.

Symptom

Erste Überprüfung

HTTP-Status 200 ohne Produktkarten

Überprüfen Sie den zurückgegebenen Body und vergewissern Sie sich, dass es sich um die erwartete Seite handelt

Sichtbare Browserdaten fehlen im HTML-Code der Antwort

Prüfen Sie, ob diese durch JavaScript oder eine Interaktion bereitgestellt werden

HTTP 429

Reduzieren Sie die Anfragehäufigkeit und beachten Sie Retry-After , falls vorhanden

HTTP 403

Überprüfen Sie die Antwort und die Zugriffsbedingungen

Gültige Karten mit fehlenden Werten

Überprüfen Sie die Feldauswahl und die Richtlinien für Pflichtfelder erneut

Ein Headless-Browser kann JavaScript ausführen und Interaktionen durchführen. In Go steuert chromedp einen Browser über das Chrome DevTools-Protokoll. Standardmäßig wird dabei ein Headless-Chrome gestartet; für die Ausführung des Browsers ist jedoch weiterhin eine geeignete Browserumgebung erforderlich.

Ersetzen Sie nicht standardmäßig jede HTTP-Anfrage durch einen Browser. Stellen Sie zunächst fest, welche Inhalte gerendert werden müssen, und warten Sie dann auf ein relevantes Element oder einen Seitenzustand, anstatt sich nur auf eine willkürliche Wartezeit zu verlassen.

Behandeln Sie ebenfalls nicht jede fehlgeschlagene Anfrage als wiederholbar. Legen Sie ein Wiederholungsbudget fest, unterscheiden Sie vorübergehende Fehler von dauerhaften Ablehnungen und beachten Sie die Crawling-Anweisungen der Quelle. Eine User-Agent-Zeichenkette identifiziert diesen Tutorial-Client; sie ist keine Garantie für den Zugriff.

Zuverlässiges Web-Scraping mit Go beginnt mit der Diagnose, in welcher Phase ein Fehler aufgetreten ist. Das Ändern von Selektoren kann ein Transport-Timeout nicht beheben, und das Erhöhen der Parallelität kann eine Seite nicht reparieren, auf der die angeforderten Daten fehlen.

Testen Sie Datensätze, bevor Sie die Parallelität erhöhen

Die Funktionen „fetch“ und „parse“ verfügen über separate Eingaben, sodass Sie sie unabhängig von einer sich ändernden Website testen können. Geben Sie parseBooks ein kleines HTML-Fixture und eine Basis-URL ein. Überprüfen Sie das „full-title“-Attribut, die ursprüngliche Preisangabe und die aufgelöste Produktadresse anhand expliziter Erwartungswerte.

Variieren Sie anschließend die Testdaten. Entfernen Sie einen Preis, benennen Sie die Kartenklasse um, lassen Sie das „title“-Attribut weg und geben Sie einen ungültigen Link an. Jede Variation sollte den Fehler erzeugen, den Ihre Pipeline erwartet. Fügen Sie eine Seite hinzu, die einen erfolgreichen HTTP-Status zurückgibt, aber keine Produktkarten enthält.

Für das Netzwerkverhalten verwenden Sie das Go-Paket „httptest“, um kontrollierte Antworten bereitzustellen. Geben Sie die Statuscodes 404 und 429 zurück, verzögern Sie eine Antwort, bis das Client-Timeout abgelaufen ist, und senden Sie einen Body, der die konfigurierte Größengrenze überschreitet. Diese Fälle decken Fehler auf, die eine einzelne erfolgreiche Live-Anfrage nicht aufdecken kann.

Das beigefügte Beispiel wurde mit lokalen Fixtures, go vetund dem Race-Detektor geprüft. Die Fixture-Suite deckte die erfolgreiche JSON-Ausgabe sowie die oben genannten Fehlerfälle ab, bei einer Anweisungsabdeckung von 84,3 %. Zwei direkte Anfragen an den Übungskatalog verifizierten die Live-Selektoren separat. Hierbei handelt es sich um eine funktionale Validierung, nicht um einen Durchsatz-Benchmark.

Bevor Sie Parallelität hinzufügen, machen Sie den Ausgabepfad für mehrere Worker sicher. Verwenden Sie einen konfigurierten HTTP-Client wieder, begrenzen Sie die Anzahl der Worker und sorgen Sie dafür, dass nur ein einziger „Eigentümer“ für das Schreiben von Datensätzen zuständig ist. Bewahren Sie Fehler mit ausreichend Seitenkontext auf, um sie untersuchen zu können, und halten Sie Zugangsdaten aus den Protokollen fern.

Beim Web-Scraping mit Go sollten Sie jeweils nur eine Begrenzung erhöhen und sowohl die Anzahl der gültigen Datensätze als auch die Anzahl der Anfragen überprüfen. Eine höhere Anzahl abgeschlossener Anfragen ist nur dann sinnvoll, wenn sie die Datensätze liefern, die Ihre Anwendung benötigt.

Wichtige Erkenntnisse

  • Trennen Sie das Abrufen vom Extrahieren. Ein HTTP-Client ruft eine Antwort ab; der Parser wandelt deren HTML in Datensätze um. Indem Sie diese Funktionen unabhängig voneinander halten, können Sie einen Selektorfehler anhand einer gespeicherten Fixture reproduzieren, ohne eine weitere Live-Anfrage stellen zu müssen.
  • Definieren Sie das Fehlerverhalten parallel zu Ihrem Ausgabeschema. Legen Sie fest, ob ein fehlender Titel, ein leerer Preis oder eine unerwartete Seite dazu führen soll, dass eine Zeile oder das gesamte Ergebnis verworfen wird. Im Beispiel wird die Seite verworfen, wodurch ein geändertes Layout sofort sichtbar wird.
  • Legen Sie die Navigation fest, bevor Sie sie automatisieren. Zulässige Ziele, besuchte Adressen, Seitenanzahlen und das Pacing lösen unterschiedliche Probleme. Behandeln Sie diese als explizite Steuerelemente, wenn Sie den Ein-Seiten-Befehl zu einem Crawl erweitern.
  • Fügen Sie Parallelität hinzu, sobald Sie den Datensätzen vertrauen können. Ein Worker-Limit und ein einziger Ausgabeverantwortlicher erleichtern die Nachvollziehbarkeit der nächsten Version. Überwachen Sie akzeptierte Datensätze und abgelehnte Seiten parallel zu den Netzwerkanfragen.

FAQ

Ist „golang.org/x/net/html“ Teil der Standardbibliothek?

Nein. Der HTML-Parser befindet sich im separaten golang.org/x/net Modul. Das Go-Standard- html und dieser Parser haben unterschiedliche Importpfade und Aufgabenbereiche. goquery nutzt den externen Parser im Hintergrund seiner Auswahl-API. Überprüfen Sie die Modulvoraussetzungen, wenn Sie ein Tutorial anwenden, anstatt davon auszugehen, dass jedes im Go-Projekt gepflegte Paket mit der Toolchain ausgeliefert wird.

Kann `goquery` auf der Festplatte gespeichertes HTML parsen?

Ja. Öffne die Datei und übergebe ihren Reader an `goquery.NewDocumentFromReader`, wobei du beide Fehlerprüfungen durchführst. Schließe die Datei in deinem aufrufenden Code; der Parser übernimmt nicht die Verantwortung für das Schließen der Datei. Wenn du absolute Links benötigst, speichere die ursprüngliche Seiten-URL separat ab, da ein lokaler Dateiname keinen Kontext für die URL-Auflösung der Website liefert.

Wie gehe ich mit Seiten um, die nicht im UTF-8-Format vorliegen?

Konvertieren Sie die Eingabe vor dem Parsen. Das Paket „golang.org/x/net/html/charset“ stellt NewReader, das einen Reader zurückgibt, der HTML mithilfe der Kodierungserkennung und des deklarierten Inhaltstyps in UTF-8 konvertiert. Behandeln Sie Fehler bei der Konvertierungseinrichtung und beachten Sie die Grenzen für die Antwortgröße in Ihrer Abrufschicht. Ein Testfall mit Akzentzeichen hilft dabei, Kodierungsprobleme zu erkennen, die ein reiner ASCII-Test übersehen würde.

Sollte ich Preise als JSON-Zahlen exportieren?

Wählen Sie die Darstellung entsprechend den Anforderungen des Nutzers. Wenn Sie Berechnungen durchführen müssen, definieren Sie die Währung und die Dezimalskalierung explizit; eine Ganzzahl in Untereinheiten oder eine dezimale Darstellung kann besser geeignet sein als binäre Gleitkommazahlen. Behalten Sie den ursprünglich angezeigten Wert als separates Feld bei, wenn Rückverfolgbarkeit wichtig ist. Entfernen Sie Satzzeichen nicht blindlings: Gruppierungs- und Dezimaltrennzeichen hängen von den Formatierungskonventionen der Quelle ab.

Fazit

Eine nützliche erste Implementierung von Web-Scraping mit Go hat einen eng gefassten, beobachtbaren Vertrag. Sie ruft eine bekannte Seite ab, validiert die Antwort, extrahiert eine definierte Datensatzstruktur und meldet Fehler. Das Buchhandlungsbeispiel bietet Ihnen diesen Ausgangspunkt mit einem lauffähigen Programm und Selektoren, die anhand des Praxis-Katalogs überprüft wurden.

Ihr nächster Schritt sollte sich an dem Problem orientieren, auf das Sie tatsächlich stoßen. Fügen Sie eine Paginierung hinzu, wenn Datensätze sich über bekannte Katalogseiten erstrecken. Setzen Sie Colly ein, wenn die Planung von Anfragen und Callbacks an Bedeutung gewinnt. Nutzen Sie das Browser-Rendering, wenn der benötigte Inhalt von JavaScript oder Interaktion abhängt. Halten Sie in jedem Fall das Ausgabeschema und die Validierungsregeln stabil genug, um die Ergebnisse vor und nach der Änderung vergleichen zu können.

Sollte die Pflege des Seitenabrufs zu einer eigenständigen betrieblichen Belastung werden, ziehen Sie für diesen Teil des Workflows die Scraper-API von WebScrapingAPI in Betracht. Ihre Go-Anwendung kann weiterhin für das Parsen, die Datensatzvalidierung und die Speicherung zuständig sein. Vergleichen Sie die zurückgegebenen Inhalte mit denselben Fixtures und Felderwartungen, die Sie bei direkten Anfragen verwenden.

Beginnen Sie damit, das Beispiel auszuführen, dessen JSON zu untersuchen und einen Selektor gezielt zu ändern, um den Fehler zu erkennen. Das Verständnis dieses Fehlerpfads bildet eine praktische Grundlage, um den Scraper sicher zu erweitern.

Über den Autor

Sorin-Gabriel Marica, Full-Stack-Entwickler @ WebScrapingAPI

Sorin-Gabriel Marica

Full-Stack-Entwickler

Sorin Marica ist Full-Stack- und DevOps-Entwickler bei WebScrapingAPI, wo er Produktfunktionen entwickelt und die Infrastruktur wartet, die für einen reibungslosen Betrieb der Plattform sorgt.

Web-Scraping mit AWS Lambda: Leitfaden für Python und Java 2026
Anleitungen

Web-Scraping mit AWS Lambda: Leitfaden für Python und Java 2026

TL;DR: Kurz gesagt: Web-Scraping mit AWS Lambda funktioniert am besten, wenn jeder Aufruf kurz, begrenzt und unabhängig wiederholbar ist. Beginnen Sie mit direktem HTTP, AWS SAM und S3 und fügen Sie erst dann SQS, Container, Browser-Rendering, Proxys oder eine verwaltete Abrufebene hinzu, wenn sich im Rahmen der Arbeitslast herausstellt, dass diese erforderlich sind.

Suciu Dan26 min read
Artikel lesen
So verwenden Sie GoSpider: Crawlen, URLs bereinigen und Daten extrahieren
Anleitungen

So verwenden Sie GoSpider: Crawlen, URLs bereinigen und Daten extrahieren

TL;DR: GoSpider ist ein Befehlszeilen-Crawler zum Auffinden von URLs, kein vollständiger Scraper für strukturierte Daten. Diese Anleitung zur Verwendung von GoSpider zeigt einen begrenzten Crawl, die saubere Verarbeitung der Ausgabe, die Übergabe von Colly an CSV sowie einen Diagnosepfad für 403-Antworten oder Seiten, die eine JavaScript-Darstellung erfordern.

Suciu Dan20 min read
Artikel lesen
Wie man Redfin scrappt: Python-Leitfaden für Immobiliendaten
Anleitungen

Wie man Redfin scrappt: Python-Leitfaden für Immobiliendaten

TL;DR: Redfin stellt versteckte API-Endpunkte zur Verfügung, die strukturiertes JSON für Immobilienangebote zurückgeben, wodurch das fragile HTML-Parsing vollständig übersprungen werden kann. Diese Anleitung führt Sie durch den Aufbau eines Python-Scrapers, der Miet- und Verkaufsdaten extrahiert, nach Standort sucht, neue Angebote über XML-Sitemaps überwacht und saubere Ergebnisse in CSV oder JSON exportiert.

Suciu Dan11 min read
Artikel lesen

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.