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:
Anda boleh pass Dapatkan URL permulaan dengan memasukkan URL secara manual, membaca URL daripada fail, membaca URL daripada pangkalan data, dsb.
Hantar permintaan http melalui Dapatkan atau Kirim untuk mendapatkan data respons.
Gunakan ungkapan biasa atau pustaka pihak ketiga untuk menghuraikan data mengikut format data respons.
Anda boleh menyimpan data dalam fail, dalam pangkalan data atau menggunakan kaedah storan lain, bergantung pada keperluan anda.
Menurut hiperpautan dan maklumat lain dalam data respons, huraikan URL baharu sebagai URL seterusnya yang akan dirangkak.
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.
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 }, } }
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 }
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 }
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 }
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 }
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!