Technologieaustausch

Go1.19-Crawler-Framework: Vereinfachen Sie das automatisierte Crawlen von Website-Vorlagen

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Einführung

Web Scraper ist ein Tool, das automatisch Daten von Websites extrahiert. Sie werden häufig in der Datenerfassung, Suchmaschinenoptimierung, Marktforschung und anderen Bereichen eingesetzt. In diesem Artikel wird detailliert beschrieben, wie Sie mit Go 1.19 ein vereinfachtes automatisiertes Tool zum Crawlen von Site-Vorlagen implementieren, um Entwicklern dabei zu helfen, Daten effizient zu sammeln.

Inhaltsverzeichnis

  1. Umweltvorbereitung
  2. Grundkonzepte von Webcrawlern
  3. Gehen Sie zur Auswahl des Crawler-Frameworks
  4. Grundlegender Prozess zum Entwerfen eines Crawlers
  5. Implementieren Sie einen einfachen Webcrawler
  6. Analysieren Sie HTML-Inhalte
  7. Gleichzeitige Verarbeitung von Crawlern
  8. Datenspeicher
  9. Fehlerbehandlungs- und Wiederholungsmechanismus
  10. Praktischer Fall: Crawlen von Nachrichten-Websites
  11. Erweiterte Funktionen und Optimierungen
  12. abschließend

1. Vorbereitung der Umgebung

Stellen Sie vor dem Start sicher, dass Go 1.19 auf Ihrem System installiert ist. Sie können die Go-Version mit dem folgenden Befehl überprüfen:

go version
  • 1

Wenn Sie Go noch nicht installiert haben, können Sie es hier herunterladen Gehen Sie zur offiziellen Website Laden Sie die neueste Version herunter und installieren Sie sie.

2. Grundkonzepte von Webcrawlern

Der grundlegende Arbeitsablauf eines Webcrawlers ist wie folgt:

  1. Anfrage senden: Senden Sie eine HTTP-Anfrage an die Zielwebseite.
  2. Erhalten Antwort: Empfangen Sie die vom Server zurückgegebene HTTP-Antwort.
  3. Inhalte analysieren: Extrahieren Sie die erforderlichen Daten aus der Antwort.
  4. Daten speichern: Speichern Sie die extrahierten Daten in einer lokalen Datei oder Datenbank.
  5. Behandeln Sie Links: Links von Webseiten extrahieren und andere Seiten weiter crawlen.

3. Wählen Sie das Crawler-Framework aus

In der Go-Sprache gibt es mehrere beliebte Crawler-Frameworks, wie zum Beispiel:

  • Colly: Ein schnelles und elegantes Crawler-Framework, das umfangreiche Funktionalität und gute Leistung bietet.
  • Goquery: Eine jQuery-ähnliche Bibliothek zum Parsen und Bearbeiten von HTML-Dokumenten.
  • HTTP-Client: Das net/http-Paket der Standardbibliothek kann die meisten einfachen HTTP-Anforderungsanforderungen erfüllen.

In diesem Artikel werden Colly und Goquery hauptsächlich zum Web-Crawling und zum Parsen von Inhalten verwendet.

4. Grundlegender Prozess zum Entwerfen eines Crawlers

Wir werden ein vereinfachtes automatisiertes Tool zum Crawlen von Site-Vorlagen entwerfen. Der grundlegende Prozess ist wie folgt:

  1. Crawler-Konfiguration initialisieren.
  2. Senden Sie eine HTTP-Anfrage, um Webseiteninhalte abzurufen.
  3. Verwenden Sie Goquery, um HTML-Inhalte zu analysieren und die erforderlichen Daten zu extrahieren.
  4. Speichern Sie Daten in einer lokalen Datei oder Datenbank.
  5. Fehlerbehandlungs- und Wiederholungsmechanismen.
  6. Verwenden Sie die gleichzeitige Verarbeitung, um die Crawling-Effizienz zu verbessern.

5. Implementieren Sie einen einfachen Webcrawler

Erstellen Sie zunächst ein neues Go-Projekt:

mkdir go_scraper
cd go_scraper
go mod init go_scraper
  • 1
  • 2
  • 3

Installieren Sie dann Colly und Goquery:

go get -u github.com/gocolly/colly
go get -u github.com/PuerkitoBio/goquery
  • 1
  • 2

Schreiben Sie als Nächstes einen einfachen Crawler zum Crawlen von Webinhalten:

package main

import (
    "fmt"
    "github.com/gocolly/colly"
)

func main() {
    // 创建一个新的爬虫实例
    c := colly.NewCollector()

    // 设置请求时的回调函数
    c.OnRequest(func(r *colly.Request) {
        fmt.Println("Visiting", r.URL.String())
    })

    // 设置响应时的回调函数
    c.OnResponse(func(r *colly.Response) {
        fmt.Println("Visited", r.Request.URL)
        fmt.Println("Response:", string(r.Body))
    })

    // 设置错误处理的回调函数
    c.OnError(func(r *colly.Response, err error) {
        fmt.Println("Error:", err)
    })

    // 设置HTML解析时的回调函数
    c.OnHTML("title", func(e *colly.HTMLElement) {
        fmt.Println("Title:", e.Text)
    })

    // 开始爬取
    c.Visit("http://example.com")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

Wenn Sie den obigen Code ausführen, wird der Inhalt von http://example.com gecrawlt und der Seitentitel gedruckt.

6. Analysieren Sie HTML-Inhalte

Um die erforderlichen Daten von der Webseite zu extrahieren, müssen wir Goquery verwenden, um den HTML-Inhalt zu analysieren. Das folgende Beispiel zeigt, wie Sie mit Goquery Links und Text aus einer Webseite extrahieren:

package main

import (
    "fmt"
    "github.com/gocolly/colly"
    "github.com/PuerkitoBio/goquery"
)

func main() {
    c := colly.NewCollector()

    c.OnHTML("body", func(e *colly.HTMLElement) {
        e.DOM.Find("a").Each(func(index int, item *goquery.Selection) {
            link, _ := item.Attr("href")
            text := item.Text()
            fmt.Printf("Link #%d: %s (%s)n", index, text, link)
        })
    })

    c.Visit("http://example.com")
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

7. Gleichzeitige Verarbeitung von Crawlern

Um die Effizienz des Crawlers zu verbessern, können wir die Parallelitätsfunktion von Colly verwenden:

package main

import (
    "fmt"
    "github.com/gocolly/colly"
    "github.com/PuerkitoBio/goquery"
    "log"
    "time"
)

func main() {
    c := colly.NewCollector(
        colly.Async(true), // 启用异步模式
    )

    c.Limit(&colly.LimitRule{
        DomainGlob:  "*",
        Parallelism: 2, // 设置并发数
        Delay:       2 * time.Second,
    })

    c.OnHTML("body", func(e *colly.HTMLElement) {
        e.DOM.Find("a").Each(func(index int, item *goquery.Selection) {
            link, _ := item.Attr("href")
            text := item.Text()
            fmt.Printf("Link #%d: %s (%s)n", index, text, link)
            c.Visit(e.Request.AbsoluteURL(link))
        })
    })

    c.OnRequest(func(r *colly.Request) {
        fmt.Println("Visiting", r.URL.String())
    })

    c.OnError(func(r *colly.Response, err error) {
        log.Println("Error:", err)
    })

    c.Visit("http://example.com")

    c.Wait() // 等待所有异步任务完成
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

8. Datenspeicherung

Speichern Sie die erfassten Daten in einer lokalen Datei oder Datenbank. Hier ist eine CSV-Datei als Beispiel:

package main

import (
    "encoding/csv"
    "fmt"
    "github.com/gocolly/colly"
    "github.com/PuerkitoBio/goquery"
    "log"
    "os"
    "time"
)

func main() {
    file, err := os.Create("data.csv")
    if err != nil {
        log.Fatalf("could not create file: %v", err)
    }
    defer file.Close()

    writer := csv.NewWriter(file)
    defer writer.Flush()

    c := colly.NewCollector(
        colly.Async(true),
    )

    c.Limit(&colly.LimitRule{
        DomainGlob:  "*",
        Parallelism: 2,
        Delay:       2 * time.Second,
    })

    c.OnHTML("body", func(e *colly.HTMLElement) {
        e.DOM.Find("a").Each(func(index int, item *goquery.Selection) {
            link, _ := item.Attr("href")
            text := item.Text()
            fmt.Printf("Link #%d: %s (%s)n", index, text, link)
            writer.Write([]string{text, link})
            c.Visit(e.Request.AbsoluteURL(link))
        })
    })

    c.OnRequest(func(r *colly.Request) {
        fmt.Println("Visiting", r.URL.String())
    })

    c.OnError(func(r *colly.Response, err error) {
        log.Println("Error:", err)
    })

    c.Visit("http://example.com")

    c.Wait()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

9. Fehlerbehandlung und Wiederholungsmechanismus

Um die Stabilität des Crawlers zu verbessern, müssen wir Anforderungsfehler behandeln und einen Wiederholungsmechanismus implementieren:

package main

import (
    "fmt"
    "github.com/gocolly/colly"
    "github.com/PuerkitoBio/goquery"
    "log"
    "os"
    "time"
)

func main() {
    file, err := os.Create("data.csv")
    if err != nil {
        log.Fatalf("could not create file: %v", err)
    }
    defer file.Close()

    writer := csv.NewWriter(file)
    defer writer.Flush()

    c := colly.NewCollector(
        colly.Async(true),
        colly.MaxDepth(1),
    )

    c.Limit(&colly.LimitRule{
        DomainGlob:  "*",
        Parallelism: 2,
        Delay:       2 * time.Second,
    })

    c.OnHTML("body", func(e *colly.HTMLElement) {
        e.DOM.Find("a").Each(func(index int, item *goquery.Selection) {
            link, _ := item.Attr("href")
            text := item.Text()
            fmt.Printf("Link #%d: %s (%s)

n", index, text, link)
            writer.Write([]string{text, link})
            c.Visit(e.Request.AbsoluteURL(link))
        })
    })

    c.OnRequest(func(r *colly.Request) {
        fmt.Println("Visiting", r.URL.String())
    })

    c.OnError(func(r *colly.Response, err error) {
        log.Println("Error:", err)
        // 重试机制
        if r.StatusCode == 0 || r.StatusCode >= 500 {
            r.Request.Retry()
        }
    })

    c.Visit("http://example.com")

    c.Wait()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

10. Praxisbeispiel: Crawlen von Nachrichten-Websites

Das folgende Beispiel zeigt, wie Sie die Titel und Links einer Nachrichten-Website extrahieren und in einer CSV-Datei speichern:

package main

import (
    "encoding/csv"
    "fmt"
    "github.com/gocolly/colly"
    "log"
    "os"
    "time"
)

func main() {
    file, err := os.Create("news.csv")
    if err != nil {
        log.Fatalf("could not create file: %v", err)
    }
    defer file.Close()

    writer := csv.NewWriter(file)
    defer writer.Flush()

    writer.Write([]string{"Title", "Link"})

    c := colly.NewCollector(
        colly.Async(true),
    )

    c.Limit(&colly.LimitRule{
        DomainGlob:  "*",
        Parallelism: 5,
        Delay:       1 * time.Second,
    })

    c.OnHTML(".news-title", func(e *colly.HTMLElement) {
        title := e.Text
        link := e.ChildAttr("a", "href")
        writer.Write([]string{title, e.Request.AbsoluteURL(link)})
        fmt.Printf("Title: %snLink: %sn", title, e.Request.AbsoluteURL(link))
    })

    c.OnRequest(func(r *colly.Request) {
        fmt.Println("Visiting", r.URL.String())
    })

    c.OnError(func(r *colly.Response, err error) {
        log.Println("Error:", err)
        if r.StatusCode == 0 || r.StatusCode >= 500 {
            r.Request.Retry()
        }
    })

    c.Visit("http://example-news-site.com")

    c.Wait()
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

11. Erweiterte Funktionen und Optimierungen

Verwenden Sie einen Proxy

Um eine Blockierung durch die Zielwebsite zu vermeiden, können Sie einen Proxy verwenden:

c.SetProxy("http://proxyserver:port")
  • 1

Maskierung des Benutzeragenten

Geben Sie vor, ein anderer Browser zu sein, indem Sie den Benutzeragenten festlegen:

c.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
  • 1

Verteilter Crawler

Sie können Collys Erweiterungsbibliothek Colly-Redis verwenden, um verteilte Crawler zu implementieren:

import (
    "github.com/gocolly/redisstorage"
)

func main() {
    c := colly.NewCollector()
    redisStorage := &redisstorage.Storage{
        Address:  "localhost:6379",
        Password: "",
        DB:       0,
        Prefix:   "colly",
    }
    c.SetStorage(redisStorage)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Dynamisches Web-Scraping

Für dynamische Webseiten können Sie einen Headless-Browser wie chromedp verwenden:

import (
    "context"
    "github.com/chromedp/chromedp"
)

func main() {
    ctx, cancel := chromedp.NewContext(context.Background())
    defer cancel()

    var res string
    err := chromedp.Run(ctx,
        chromedp.Navigate("http://example.com"),
        chromedp.WaitVisible(`#some-element`),
        chromedp.InnerHTML(`#some-element`, &res),
    )

    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(res)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

12. Fazit

Durch die ausführliche Einführung dieses Artikels haben wir gelernt, wie man mit Go 1.19 ein vereinfachtes automatisiertes Tool zum Crawlen von Site-Vorlagen implementiert. Wir begannen mit dem grundlegenden Crawler-Designprozess und vertieften uns nach und nach in wichtige Aspekte wie HTML-Parsing, gleichzeitige Verarbeitung, Datenspeicherung und Fehlerbehandlung und demonstrierten anhand spezifischer Codebeispiele, wie Webseitendaten gecrawlt und verarbeitet werden.

Die leistungsstarken Funktionen zur Parallelitätsverarbeitung und die umfangreichen Bibliotheken von Drittanbietern machen die Go-Sprache zur idealen Wahl für die Entwicklung effizienter und stabiler Webcrawler. Durch kontinuierliche Optimierung und Erweiterung können komplexere und fortschrittlichere Crawler-Funktionen erreicht werden, um Lösungen für verschiedene Datenerfassungsanforderungen bereitzustellen.

Ich hoffe, dieser Artikel kann Ihnen wertvolle Hinweise zur Implementierung von Webcrawlern in der Go-Sprache geben und Sie zu weiteren Erkundungen und Innovationen in diesem Bereich inspirieren.