Go语言因其高性能、简洁语法和原生并发支持,在网络爬虫和数据抓取领域备受关注。本文结合代码示例,讲解Go语言协程、并发请求和高效数据解析的实战方法。
一、基础爬虫示例
使用Go的标准库net/http实现简单HTTP请求:
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
resp, err := http.Get("https://httpbin.org/get")
if err != nil {
fmt.Println("请求失败", err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
这是最基本的同步请求方式,处理大量URL效率低。
二、使用协程并发请求
Go协程轻量、创建成本低,可实现高并发抓取:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"sync"
)
func fetch(url string, wg *sync.WaitGroup) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
fmt.Println("请求失败", url, err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("%s 前100字符: %s\n", url, string(body[:100]))
}
func main() {
urls := []string{"https://httpbin.org/get", "https://example.com"}
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go fetch(url, &wg)
}
wg.Wait()
}
协程与WaitGroup结合,轻松实现并发请求,提高抓取效率。
三、数据解析
可使用Go的golang.org/x/net/html库解析HTML内容:
package main
import (
"fmt"
"golang.org/x/net/html"
"strings"
)
func parseHTML(htmlStr string) {
doc, _ := html.Parse(strings.NewReader(htmlStr))
var f func(*html.Node)
f = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "title" {
fmt.Println("标题:", n.FirstChild.Data)
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
}
f(doc)
}
func main() {
htmlContent := `<html><head><title>示例</title></head></html>`
parseHTML(htmlContent)
}
结合并发请求,可以实现高效抓取和解析。
四、高级优化技巧
-
限制并发量:使用带缓冲的channel控制协程数量,避免过多请求被封禁。
sem := make(chan struct{}, 5)
sem <- struct{}{} // 获取信号
<-sem // 释放信号 -
错误重试:对请求失败的URL进行重试。
-
缓存与存储:保存已抓取数据,减少重复请求。
-
异步数据处理:使用goroutine解析数据,提升整体吞吐量。
五、总结
Go语言通过goroutine、channel和高效网络库,能够轻松实现高并发爬虫。掌握协程并发、数据解析与优化技巧,能够