Go Web Scraping: HTML Parsing from Zero to Hero
Takashi Yamamoto
Infrastructure Engineer · Leapcell

Installation und Verwendung von Goquery
Installation
Ausführen:
go get github.com/PuerkitoBio/goquery
Importieren
import "github.com/PuerkitoBio/goquery"
Die Seite laden
Nehmen wir die IMDb-Seite mit den beliebtesten Filmen als Beispiel:
package main import ( "fmt" "log" "net/http" "github.com/PuerkitoBio/goquery" ) func main() { res, err := http.Get("https://www.imdb.com/chart/moviemeter/") if err != nil { log.Fatal(err) } defer res.Body.Close() if res.StatusCode != 200 { log.Fatalf("status code error: %d %s", res.StatusCode, res.Status) }
Das Dokumentobjekt abrufen
doc, err := goquery.NewDocumentFromReader(res.Body) if err != nil { log.Fatal(err) } // Andere Erstellungsmethoden // doc, err := goquery.NewDocumentFromReader(reader io.Reader) // doc, err := goquery.NewDocument(url string) // doc, err := goquery.NewDocument(strings.NewReader("<p>Example content</p>"))
Elemente auswählen
Elementauswahl
Auswahl basierend auf grundlegenden HTML-Elementen. Zum Beispiel findet dom.Find("p")
alle p
-Tags. Es unterstützt verkettete Aufrufe:
ele.Find("h2").Find("a")
Attributauswahl
Filtert Elemente nach Elementattributen und -werten, mit mehreren Übereinstimmungsmethoden:
Find("div[my]") // Filtert div-Elemente mit dem Attribut my Find("div[my=zh]") // Filtert div-Elemente, deren my-Attribut zh ist Find("div[my!=zh]") // Filtert div-Elemente, deren my-Attribut nicht gleich zh ist Find("div[my|=zh]") // Filtert div-Elemente, deren my-Attribut zh ist oder mit zh- beginnt Find("div[my*=zh]") // Filtert div-Elemente, deren my-Attribut die Zeichenkette zh enthält Find("div[my~=zh]") // Filtert div-Elemente, deren my-Attribut das Wort zh enthält Find("div[my$=zh]") // Filtert div-Elemente, deren my-Attribut mit zh endet Find("div[my^=zh]") // Filtert div-Elemente, deren my-Attribut mit zh beginnt
parent > child
Auswahl
Filtert die Kindelemente unter einem bestimmten Element. Zum Beispiel filtert dom.Find("div>p")
die p
-Tags unter dem div
-Tag.
element + next
Benachbarte Auswahl
Verwenden Sie sie, wenn die Elemente unregelmäßig ausgewählt werden, aber das vorherige Element ein Muster aufweist. Zum Beispiel filtert dom.Find("p[my=a]+p")
die benachbarten p
-Tags, deren my
-Attributwert des p
-Tags a
ist.
element~next
Geschwisterauswahl
Filtert die nicht-benachbarten Tags unter dem gleichen Elternelement. Zum Beispiel filtert dom.Find("p[my=a]~p")
die Geschwister-p
-Tags, deren my
-Attributwert des p
-Tags a
ist.
ID-Auswahl
Sie beginnt mit #
und findet das Element exakt. Zum Beispiel findet dom.Find("#title")
den Inhalt mit id=title
, und Sie können das Tag dom.Find("p#title")
angeben.
ele.Find("#title")
Klassenauswahl
Sie beginnt mit .
und filtert die Elemente mit dem angegebenen Klassennamen. Zum Beispiel dom.Find(".content1")
, und Sie können das Tag dom.Find("div.content1")
angeben.
ele.Find(".title")
Auswahl ODER (|) Operation
Kombinieren Sie mehrere Selektoren, getrennt durch Kommas. Die Filterung erfolgt, wenn eine von ihnen erfüllt ist. Zum Beispiel Find("div,span")
.
func main() { html := `<body> <div lang="zh">DIV1</div> <span> <div>DIV5</div> </span> </body>` dom, err := goquery.NewDocumentFromReader(strings.NewReader(html)) if err != nil { log.Fatalln(err) } dom.Find("div,span").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Html()) }) }
Filter
:contains
Filter
Filtert Elemente, die den angegebenen Text enthalten. Zum Beispiel filtert dom.Find("p:contains(a)")
die p
-Tags, die a
enthalten.
dom.Find("div:contains(DIV2)").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) })
:has(selector)
Filtert Elemente, die die angegebenen Elementknoten enthalten.
:empty
Filtert Elemente, die keine Kindelemente haben.
:first-child
und :first-of-type
Filter
Find("p:first-child")
filtert das erste p
-Tag; first-of-type
erfordert, dass es das erste Element dieses Typs ist.
:last-child
und :last-of-type
Filter
Das Gegenteil von :first-child
und :first-of-type
.
:nth-child(n)
und :nth-of-type(n)
Filter
:nth-child(n)
filtert das n
-te Element des Elternelements; :nth-of-type(n)
filtert das n
-te Element des gleichen Typs.
:nth-last-child(n)
und :nth-last-of-type(n)
Filter
Berechnet in umgekehrter Reihenfolge, wobei das letzte Element das erste ist.
:only-child
und :only-of-type
Filter
Find(":only-child")
filtert das einzige Kindelement im Elternelement; Find(":only-of-type")
filtert das einzige Element des gleichen Typs.
Inhalt abrufen
ele.Html() ele.Text()
Durchlauf
Verwenden Sie die Each
-Methode, um die ausgewählten Elemente zu durchlaufen:
ele.Find(".item").Each(func(index int, elA *goquery.Selection) { href, _ := elA.Attr("href") fmt.Println(href) })
Eingebaute Funktionen
Array-Positionierungsfunktionen
Eq(index int) *Selection First() *Selection Get(index int) *html.Node Index...() int Last() *Selection Slice(start, end int) *Selection
Erweiterte Funktionen
Add...() AndSelf() Union()
Filterfunktionen
End() Filter...() Has...() Intersection() Not...()
Schleifendurchlauffunktionen
Each(f func(int, *Selection)) *Selection EachWithBreak(f func(int, *Selection) bool) *Selection Map(f func(int, *Selection) string) (result []string)
Funktionen zur Dokumentenänderung
After...() Append...() Before...() Clone() Empty() Prepend...() Remove...() ReplaceWith...() Unwrap() Wrap...() WrapAll...() WrapInner...()
Attributmanipulationsfunktionen
Attr*(), RemoveAttr(), SetAttr() AttrOr(e string, d string) AddClass(), HasClass(), RemoveClass(), ToggleClass() Html() Length() Size() Text()
Knotensuchfunktionen
Contains() Is...()
Funktionen zum Durchlaufen der Dokumentenstruktur
Children...() Contents() Find...() Next...() *Selection NextAll() *Selection Parent[s]...() Prev...() *Selection Siblings...()
Typdefinitionen
Document Selection Matcher
Hilfsfunktionen
NodeName OuterHtml
Beispiele
Beispiel für den Einstieg
func main() { html := `<html> <body> <h1 id="title">O Captain! My Captain!</h1> <p class="content1"> O Captain! my Captain! our fearful trip is done, The ship has weather’d every rack, the prize we sought is won, The port is near, the bells I hear, the people all exulting, While follow eyes the steady keel, the vessel grim and daring; </p> </body> </html>` dom, err := goquery.NewDocumentFromReader(strings.NewReader(html)) if err != nil { log.Fatalln(err) } dom.Find("p").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) }
Beispiel für das Crawlen von IMDb-Informationen zu beliebten Filmen
package main import ( "fmt" "log" "github.com/PuerkitoBio/goquery" ) func main() { doc, err := goquery.NewDocument("https://www.imdb.com/chart/moviemeter/") if err != nil { log.Fatal(err) } doc.Find(".titleColumn a").Each(func(i int, selection *goquery.Selection) { title := selection.Text() href, _ := selection.Attr("href") fmt.Printf("Movie Name: %s, Link: https://www.imdb.com%s\n", title, href) }) }
Die obigen Beispiele extrahieren die Filmnamen und Linkinformationen von der IMDb-Seite mit den beliebtesten Filmen. In der tatsächlichen Anwendung können Sie die Selektoren und die Verarbeitungslogik entsprechend Ihren Bedürfnissen anpassen.
Leapcell: Die Next-Gen Serverless Plattform für Webhosting
Schließlich möchte ich die beste Plattform zum Bereitstellen von Go-Diensten empfehlen: Leapcell
1. Multi-Sprachen Unterstützung
- Entwickeln Sie mit JavaScript, Python, Go oder Rust.
2. Stellen Sie unbegrenzt Projekte kostenlos bereit
- Zahlen Sie nur für die Nutzung - keine Anfragen, keine Gebühren.
3. Unschlagbare Kosteneffizienz
- Pay-as-you-go ohne Leerlaufgebühren.
- Beispiel: 25 US-Dollar unterstützen 6,94 Millionen Anfragen bei einer durchschnittlichen Antwortzeit von 60 ms.
4. Optimierte Entwicklererfahrung
- Intuitive Benutzeroberfläche für mühelose Einrichtung.
- Vollautomatische CI/CD-Pipelines und GitOps-Integration.
- Echtzeitmetriken und -protokollierung für verwertbare Erkenntnisse.
5. Mühelose Skalierbarkeit und hohe Leistung
- Automatische Skalierung, um hohe Parallelität problemlos zu bewältigen.
- Kein operativer Overhead - konzentrieren Sie sich einfach auf das Erstellen.
Entdecken Sie mehr in der Dokumentation!
Leapcell Twitter: https://x.com/LeapcellHQ