Rumah  >  Artikel  >  pembangunan bahagian belakang  >  golang tidak mengarahkan crawler

golang tidak mengarahkan crawler

PHPz
PHPzasal
2023-05-10 10:06:06481semak imbas

1. Kata Pengantar

Dengan perkembangan Internet, skop aplikasi perangkak web semakin meluas. Dalam kehidupan seharian, kita boleh memperoleh pelbagai maklumat melalui perangkak web, seperti berita, saham, cuaca, filem, muzik, dll. Terutamanya dalam bidang analisis data besar dan kecerdasan buatan, perangkak web memainkan peranan penting. Artikel ini menerangkan terutamanya cara menggunakan bahasa golang untuk menulis perangkak bukan arah (iaitu, tiada tapak web sasaran khusus) untuk mendapatkan maklumat di Internet.

2. Pengenalan kepada golang

Golang ialah bahasa pengaturcaraan yang dibangunkan oleh Google Disebabkan keselarasannya, prestasi tinggi, kesederhanaan dan kemudahan pembelajaran, ia semakin digemari oleh pengaturcara. Versi golang yang digunakan dalam artikel ini ialah 1.14.2.

3. Idea pelaksanaan

Perangkak ini terbahagi kepada langkah berikut:

  1. Dapatkan URL permulaan

Anda boleh pass Dapatkan URL permulaan dengan memasukkan URL secara manual, membaca URL daripada fail, membaca URL daripada pangkalan data, dsb.

  1. Hantar permintaan http

Hantar permintaan http melalui Dapatkan atau Kirim untuk mendapatkan data respons.

  1. Menghuraikan data respons

Gunakan ungkapan biasa atau pustaka pihak ketiga untuk menghuraikan data mengikut format data respons.

  1. Menyimpan data

Anda boleh menyimpan data dalam fail, dalam pangkalan data atau menggunakan kaedah storan lain, bergantung pada keperluan anda.

  1. Menghuraikan URL baharu

Menurut hiperpautan dan maklumat lain dalam data respons, huraikan URL baharu sebagai URL seterusnya yang akan dirangkak.

  1. Ulang langkah di atas

Mengikut URL baharu, hantar permintaan http sekali lagi, hurai data respons, simpan data, hurai URL baharu, ulang sehingga tiada yang baru Sehingga URL.

4. Pelaksanaan kod

Dalam golang, gunakan pakej net/http untuk menghantar permintaan http dan gunakan pakej regexp atau pustaka pihak ketiga untuk menghuraikan data respons yang digunakan oleh artikel ini perpustakaan goquery.

  1. Fungsi permulaan

Pertama, kita perlu menentukan fungsi awal, yang bertanggungjawab untuk mendapatkan URL permulaan, menyediakan klien http, dsb.

func init() {
    // 获取起始网址
    flag.StringVar(&startUrl, "url", "", "请输入起始网址")
    flag.Parse()

    // 设置http客户端
    client = &http.Client{
        Timeout: 30 * time.Second,
        CheckRedirect: func(req *http.Request, via []*http.Request) error {
            return http.ErrUseLastResponse
        },
    }
}
  1. Hantar fungsi permintaan http

Tentukan fungsi yang bertanggungjawab untuk menghantar permintaan http dan mendapatkan data tindak balas.

func GetHtml(url string) (string, error) {
    resp, err := client.Get(url)
    if err != nil {
        log.Println(err)
        return "", err
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Println(err)
        return "", err
    }

    return string(body), nil
}
  1. Menghuraikan fungsi data respons

Gunakan pustaka goquery untuk menghuraikan data tindak balas adalah seperti berikut:

func ParseSingleHTML(html string, query string) []string {
    doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
    if err != nil {
        log.Println(err)
        return nil
    }

    result := make([]string, 0)
    doc.Find(query).Each(func(i int, selection *goquery.Selection) {
        href, ok := selection.Attr("href")
        if ok {
            result = append(result, href)
        }
    })

    return result
}
  1. Data storan. fungsi

Tentukan fungsi yang bertanggungjawab untuk menyimpan data ke dalam fail.

func SaveData(data []string) error {
    file, err := os.OpenFile("data.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        log.Println(err)
        return err
    }
    defer file.Close()

    writer := bufio.NewWriter(file)
    for _, line := range data {
        _, err := writer.WriteString(line + "
")
        if err != nil {
            log.Println(err)
            return err
        }
    }
    writer.Flush()

    return nil
}
  1. Menghuraikan fungsi URL baharu

Gunakan ungkapan biasa untuk menghuraikan URL baharu dalam hiperpautan.

func ParseHref(url, html string) []string {
    re := regexp.MustCompile(`<a[sS]+?href="(.*?)"[sS]*?>`)
    matches := re.FindAllStringSubmatch(html, -1)

    result := make([]string, 0)
    for _, match := range matches {
        href := match[1]
        if strings.HasPrefix(href, "//") {
            href = "http:" + href
        } else if strings.HasPrefix(href, "/") {
            href = strings.TrimSuffix(url, "/") + href
        } else if strings.HasPrefix(href, "http://") || strings.HasPrefix(href, "https://") {
            // do nothing
        } else {
            href = url + "/" + href
        }
        result = append(result, href)
    }

    return result
}
  1. Fungsi utama

Akhir sekali, kita perlu mentakrifkan fungsi utama untuk melaksanakan keseluruhan proses perangkak.

func main() {
    // 确认起始网址是否为空
    if startUrl == "" {
        fmt.Println("请指定起始网址")
        return
    }

    // 初始化待访问队列
    queue := list.New()
    queue.PushBack(startUrl)

    // 初始化已访问集合
    visited := make(map[string]bool)

    // 循环爬取
    for queue.Len() > 0 {
        // 从队列中弹出一个网址
        elem := queue.Front()
        queue.Remove(elem)
        url, ok := elem.Value.(string)
        if !ok {
            log.Println("网址格式错误")
            continue
        }

        // 确认该网址是否已经访问过
        if visited[url] {
            continue
        }
        visited[url] = true

        // 发送http请求,获取响应数据
        html, err := GetHtml(url)
        if err != nil {
            continue
        }

        // 解析响应数据,获取新的网址
        hrefs := ParseHref(url, html)
        queue.PushBackList(list.New().Init())
        for _, href := range hrefs {
            if !visited[href] {
                hrefHtml, err := GetHtml(href)
                if err != nil {
                    continue
                }
                hrefUrls := ParseSingleHTML(hrefHtml, "a")

                // 将新的网址加入队列
                queue.PushBackList(list.New().Init())
                for _, hrefUrl := range hrefUrls {
                    queue.PushBack(hrefUrl)
                }
            }
        }

        // 存储数据到文件
        data := ParseSingleHTML(html, "title")
        err = SaveData(data)
        if err != nil {
            continue
        }
    }
}

5. Ringkasan

Di atas adalah proses asas dan kaedah pelaksanaan menggunakan golang untuk menulis perangkak tidak terarah. Sudah tentu, ini hanyalah contoh mudah Dalam pembangunan sebenar, strategi anti-crawler, keselamatan benang dan isu lain juga perlu dipertimbangkan. Semoga dapat memberi manfaat kepada pembaca.

Atas ialah kandungan terperinci golang tidak mengarahkan crawler. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:golang slice to jsonArtikel seterusnya:golang slice to json