Κοινή χρήση τεχνολογίας

Πλαίσιο ανιχνευτή Go1.19: απλοποίηση της αυτοματοποιημένης ανίχνευσης προτύπων ιστότοπου

2024-07-12

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

εισαγωγή

Το Web Scraper είναι ένα εργαλείο που εξάγει αυτόματα δεδομένα από ιστότοπους. Χρησιμοποιούνται ευρέως στη συλλογή δεδομένων, στη βελτιστοποίηση μηχανών αναζήτησης, στην έρευνα αγοράς και σε άλλους τομείς. Αυτό το άρθρο θα παρουσιάσει λεπτομερώς τον τρόπο χρήσης του Go 1.19 για την εφαρμογή ενός απλοποιημένου αυτοματοποιημένου εργαλείου ανίχνευσης προτύπων ιστότοπου για να βοηθήσει τους προγραμματιστές να συλλέγουν δεδομένα αποτελεσματικά.

Πίνακας περιεχομένων

  1. Περιβαλλοντική προετοιμασία
  2. Βασικές έννοιες των ανιχνευτών Ιστού
  3. Μετάβαση στην επιλογή πλαισίου ανίχνευσης
  4. Βασική διαδικασία σχεδιασμού ενός ερπυστριοφόρου
  5. Εφαρμόστε ένα απλό πρόγραμμα ανίχνευσης ιστού
  6. Ανάλυση περιεχομένου HTML
  7. Επεξεργασία ταυτόχρονης ανίχνευσης
  8. αποθήκευση δεδομένων
  9. Μηχανισμός χειρισμού σφαλμάτων και επανάληψης δοκιμής
  10. Πρακτική περίπτωση: ανίχνευση ιστοσελίδων ειδήσεων
  11. Προηγμένες δυνατότητες και βελτιστοποιήσεις
  12. Συμπερασματικά

1. Προετοιμασία περιβάλλοντος

Πριν ξεκινήσετε, βεβαιωθείτε ότι έχετε εγκαταστήσει το Go 1.19 στο σύστημά σας. Μπορείτε να ελέγξετε την έκδοση Go με την ακόλουθη εντολή:

go version
  • 1

Εάν δεν έχετε εγκαταστήσει ακόμα το Go, μπορείτε να το κατεβάσετε από Μεταβείτε στον επίσημο ιστότοπο Κατεβάστε και εγκαταστήστε την πιο πρόσφατη έκδοση.

2. Βασικές έννοιες των web crawlers

Η βασική ροή εργασίας ενός προγράμματος ανίχνευσης ιστού είναι η εξής:

  1. Στείλε αίτημα: Στείλτε ένα αίτημα HTTP στην ιστοσελίδα προορισμού.
  2. Λάβετε απάντηση: Λήψη της απόκρισης HTTP που επιστρέφεται από τον διακομιστή.
  3. αναλύστε το περιεχόμενο: Εξάγετε τα απαιτούμενα δεδομένα από την απάντηση.
  4. Αποθήκευση δεδομένων: Αποθηκεύστε τα εξαγόμενα δεδομένα σε ένα τοπικό αρχείο ή βάση δεδομένων.
  5. Χειριστείτε συνδέσμους: Εξαγωγή συνδέσμων από ιστοσελίδες και συνεχίστε την ανίχνευση άλλων σελίδων.

3. Μετάβαση στην επιλογή πλαισίου ανίχνευσης

Στη γλώσσα Go, υπάρχουν πολλά δημοφιλή πλαίσια ανίχνευσης, όπως:

  • Colly: Ένα γρήγορο και κομψό πλαίσιο ανίχνευσης που παρέχει πλούσια λειτουργικότητα και καλή απόδοση.
  • Goquery: Μια βιβλιοθήκη που μοιάζει με jQuery για ανάλυση και χειρισμό εγγράφων HTML.
  • πελάτης HTTP: Το πακέτο net/http της τυπικής βιβλιοθήκης μπορεί να καλύψει τις περισσότερες απλές ανάγκες αιτημάτων HTTP.

Αυτό το άρθρο θα χρησιμοποιεί κυρίως το Colly και το Goquery για ανίχνευση ιστού και ανάλυση περιεχομένου.

4. Βασική διαδικασία σχεδιασμού ερπυστριοφόρου

Θα σχεδιάσουμε ένα απλοποιημένο αυτοματοποιημένο εργαλείο ανίχνευσης προτύπων ιστότοπου Η βασική διαδικασία είναι η εξής:

  1. Εκκινήστε τη διαμόρφωση του προγράμματος ανίχνευσης.
  2. Στείλτε ένα αίτημα HTTP για να αποκτήσετε περιεχόμενο ιστοσελίδας.
  3. Χρησιμοποιήστε το Goquery για να αναλύσετε περιεχόμενο HTML και να εξαγάγετε τα απαιτούμενα δεδομένα.
  4. Αποθηκεύστε δεδομένα σε τοπικό αρχείο ή βάση δεδομένων.
  5. Μηχανισμοί χειρισμού σφαλμάτων και επανάληψης δοκιμής.
  6. Χρησιμοποιήστε ταυτόχρονη επεξεργασία για να βελτιώσετε την αποτελεσματικότητα ανίχνευσης.

5. Εφαρμόστε ένα απλό πρόγραμμα ανίχνευσης ιστού

Πρώτα, δημιουργήστε ένα νέο έργο Go:

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

Στη συνέχεια, εγκαταστήστε το Colly and Goquery:

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

Στη συνέχεια, γράψτε ένα απλό πρόγραμμα ανίχνευσης για ανίχνευση περιεχομένου ιστού:

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

Η εκτέλεση του παραπάνω κώδικα θα ανιχνεύσει το περιεχόμενο του http://example.com και θα εκτυπώσει τον τίτλο της σελίδας.

6. Ανάλυση περιεχομένου HTML

Για να εξαγάγουμε τα απαιτούμενα δεδομένα από την ιστοσελίδα, πρέπει να χρησιμοποιήσουμε το Goquery για να αναλύσουμε το περιεχόμενο HTML. Το ακόλουθο παράδειγμα δείχνει πώς να χρησιμοποιήσετε το Goquery για να εξαγάγετε συνδέσμους και κείμενο από μια ιστοσελίδα:

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. Ταυτόχρονη επεξεργασία ανιχνευτών

Για να βελτιώσουμε την αποτελεσματικότητα του ανιχνευτή, μπορούμε να χρησιμοποιήσουμε τη συνάρτηση συγχρονισμού του 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. Αποθήκευση δεδομένων

Αποθηκεύστε τα δεδομένα που καταγράφηκαν σε ένα τοπικό αρχείο ή βάση δεδομένων. Ακολουθεί ένα αρχείο CSV ως παράδειγμα:

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. Μηχανισμός χειρισμού σφαλμάτων και επανάληψης δοκιμής

Για να βελτιώσουμε τη σταθερότητα του ανιχνευτή, πρέπει να χειριστούμε τα σφάλματα αιτημάτων και να εφαρμόσουμε έναν μηχανισμό επανάληψης δοκιμής:

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. Πρακτική περίπτωση: ανίχνευση ιστοσελίδων ειδήσεων

Το παρακάτω παράδειγμα δείχνει πώς να ξύσετε τους τίτλους και τους συνδέσμους ενός ιστότοπου ειδήσεων και να τους αποθηκεύσετε σε ένα αρχείο 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. Προηγμένες λειτουργίες και βελτιστοποιήσεις

Χρησιμοποιήστε έναν διακομιστή μεσολάβησης

Για να αποφύγετε τον αποκλεισμό από τον ιστότοπο-στόχο, μπορείτε να χρησιμοποιήσετε έναν διακομιστή μεσολάβησης:

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

Μεταμφιεσμένος πράκτορας χρήστη

Προσποιηθείτε ότι είστε διαφορετικό πρόγραμμα περιήγησης ορίζοντας τον παράγοντα χρήστη:

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

Κατανεμημένο πρόγραμμα ανίχνευσης

Μπορείτε να χρησιμοποιήσετε τη βιβλιοθήκη επέκτασης Colly Colly-Redis για να εφαρμόσετε κατανεμημένους ανιχνευτές:

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

Δυναμική απόξεση ιστού

Για δυναμικές ιστοσελίδες, μπορείτε να χρησιμοποιήσετε ένα πρόγραμμα περιήγησης χωρίς κεφάλι, όπως το 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. Συμπέρασμα

Μέσα από τη λεπτομερή εισαγωγή αυτού του άρθρου, μάθαμε πώς να χρησιμοποιούμε το Go 1.19 για την υλοποίηση ενός απλοποιημένου αυτοματοποιημένου εργαλείου ανίχνευσης προτύπων ιστότοπου. Ξεκινήσαμε από τη βασική διαδικασία σχεδιασμού του προγράμματος ανίχνευσης και σταδιακά προχωρήσαμε σε βασικές πτυχές, όπως η ανάλυση HTML, η ταυτόχρονη επεξεργασία, η αποθήκευση δεδομένων και ο χειρισμός σφαλμάτων, και δείξαμε πώς να ανιχνεύουμε και να επεξεργαζόμαστε δεδομένα ιστοσελίδας μέσω συγκεκριμένων παραδειγμάτων κώδικα.

Οι ισχυρές δυνατότητες επεξεργασίας ταυτόχρονης επεξεργασίας της γλώσσας Go και οι πλούσιες βιβλιοθήκες τρίτων την καθιστούν ιδανική επιλογή για τη δημιουργία αποτελεσματικών και σταθερών ανιχνευτών ιστού. Μέσω της συνεχούς βελτιστοποίησης και επέκτασης, μπορούν να επιτευχθούν πιο σύνθετες και προηγμένες λειτουργίες ανιχνευτή για την παροχή λύσεων για διάφορες ανάγκες συλλογής δεδομένων.

Ελπίζω ότι αυτό το άρθρο μπορεί να σας προσφέρει πολύτιμη αναφορά για την εφαρμογή ανιχνευτών ιστού στη γλώσσα Go και να σας εμπνεύσει να διεξάγετε περισσότερη εξερεύνηση και καινοτομία σε αυτόν τον τομέα.