Condivisione della tecnologia

Framework del crawler Go1.19: semplifica la scansione automatizzata dei modelli di sito

2024-07-12

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

introduzione

Web Scraper è uno strumento che estrae automaticamente i dati dai siti web. Sono ampiamente utilizzati nella raccolta dati, nell'ottimizzazione dei motori di ricerca, nelle ricerche di mercato e in altri campi. Questo articolo introdurrà in dettaglio come utilizzare Go 1.19 per implementare uno strumento di scansione automatizzato e semplificato dei modelli di sito per aiutare gli sviluppatori a raccogliere dati in modo efficiente.

Sommario

  1. Preparazione ambientale
  2. Concetti di base dei web crawler
  3. Vai alla selezione del framework del crawler
  4. Processo di base della progettazione di un crawler
  5. Implementa un semplice web crawler
  6. Analizzare il contenuto HTML
  7. Elaborazione simultanea dei crawler
  8. archivio dati
  9. Gestione degli errori e meccanismo di ripetizione
  10. Caso pratico: scansione di siti Web di notizie
  11. Funzionalità avanzate e ottimizzazioni
  12. Insomma

1. Preparazione dell'ambiente

Prima di iniziare, assicurati di avere Go 1.19 installato sul tuo sistema. Puoi controllare la versione Go con il seguente comando:

go version
  • 1

Se non hai ancora installato Go, puoi scaricarlo da Vai al sito ufficiale Scarica e installa la versione più recente.

2. Concetti di base dei web crawler

Il flusso di lavoro di base di un web crawler è il seguente:

  1. invia richiesta: invia una richiesta HTTP alla pagina Web di destinazione.
  2. Ottieni risposta: riceve la risposta HTTP restituita dal server.
  3. analizzare il contenuto: estrae i dati richiesti dalla risposta.
  4. Memorizzazione dei dati: salva i dati estratti in un file o database locale.
  5. Gestire i collegamenti: estrae collegamenti da pagine Web e continua a eseguire la scansione di altre pagine.

3. Vai alla selezione del framework del crawler

Nel linguaggio Go, esistono diversi framework di crawler popolari, come:

  • Colly: un framework crawler veloce ed elegante che offre funzionalità avanzate e buone prestazioni.
  • Goquery: una libreria simile a jQuery per l'analisi e la manipolazione di documenti HTML.
  • Client HTTP: il pacchetto net/http della libreria standard può soddisfare le esigenze di richiesta HTTP più semplici.

Questo articolo utilizzerà principalmente Colly e Goquery per la scansione del web e l'analisi dei contenuti.

4. Processo di base della progettazione di un crawler

Progetteremo uno strumento di scansione automatizzato e semplificato dei modelli di sito. Il processo di base è il seguente:

  1. Inizializza la configurazione del crawler.
  2. Invia una richiesta HTTP per ottenere il contenuto della pagina web.
  3. Utilizza Goquery per analizzare il contenuto HTML ed estrarre i dati richiesti.
  4. Salvare i dati in un file locale o in un database.
  5. Gestione degli errori e meccanismi di ripetizione.
  6. Utilizza l'elaborazione simultanea per migliorare l'efficienza della scansione.

5. Implementa un semplice web crawler

Innanzitutto, crea un nuovo progetto Go:

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

Quindi, installa Colly e Goquery:

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

Successivamente, scrivi un semplice crawler per eseguire la scansione del contenuto web:

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

L'esecuzione del codice precedente eseguirà la scansione del contenuto di http://example.com e stamperà il titolo della pagina.

6. Analizzare il contenuto HTML

Per estrarre i dati richiesti dalla pagina web, dobbiamo utilizzare Goquery per analizzare il contenuto HTML. L'esempio seguente mostra come utilizzare Goquery per estrarre collegamenti e testo da una pagina web:

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. Elaborazione simultanea dei crawler

Per migliorare l'efficienza del crawler possiamo utilizzare la funzione di concorrenza di Colly:

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. Archiviazione dei dati

Salvare i dati acquisiti in un file o database locale. Ecco un file CSV come esempio:

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. Gestione degli errori e meccanismo di ripetizione

Per migliorare la stabilità del crawler, dobbiamo gestire gli errori di richiesta e implementare un meccanismo di ripetizione:

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. Caso pratico: scansione di siti Web di notizie

L'esempio seguente mostra come recuperare i titoli e i collegamenti di un sito Web di notizie e salvarli in un file CSV:

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. Funzioni avanzate e ottimizzazioni

Utilizza un proxy

Per evitare di essere bloccato dal sito Web di destinazione, puoi utilizzare un proxy:

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

Mascheramento dell'agente utente

Fai finta di essere un browser diverso impostando l'agente utente:

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

Crawler distribuito

Puoi utilizzare la libreria di estensioni Colly-Redis per implementare crawler distribuiti:

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

Scraping web dinamico

Per le pagine Web dinamiche, puoi utilizzare un browser headless come Chromedp:

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. Conclusione

Attraverso l'introduzione dettagliata di questo articolo, abbiamo imparato come utilizzare Go 1.19 per implementare uno strumento semplificato per la scansione automatizzata dei modelli di sito. Abbiamo iniziato dal processo di progettazione di base del crawler e gradualmente abbiamo approfondito aspetti chiave come l'analisi HTML, l'elaborazione simultanea, l'archiviazione dei dati e la gestione degli errori, oltre a dimostrare come eseguire la scansione ed elaborare i dati delle pagine Web attraverso esempi di codice specifici.

Le potenti capacità di elaborazione della concorrenza del linguaggio Go e le ricche librerie di terze parti lo rendono la scelta ideale per creare web crawler efficienti e stabili. Attraverso l'ottimizzazione e l'espansione continua, è possibile ottenere funzioni crawler più complesse e avanzate per fornire soluzioni per varie esigenze di raccolta dati.

Spero che questo articolo possa fornirti preziosi riferimenti per l'implementazione dei web crawler nella lingua Go e ispirarti a condurre ulteriori esplorazioni e innovazioni in questo campo.