Go语言爬虫实战(线程池)
package main
import (
"fmt"
"sync"
"time"
)
var (
urls = []string{
// ... 省略urls列表 ...
}
wg sync.WaitGroup
mut sync.Mutex
)
func crawl(url string, ch chan<- string) {
defer wg.Done()
time.Sleep(2 * time.Second) // 模拟网络延迟
mut.Lock()
fmt.Println("Crawling", url)
mut.Unlock()
ch <- url // 将爬取的URL发送到通道
}
func main() {
start := time.Now()
ch := make(chan string, 3) // 创建一个通道,容量为3
for _, url := range urls {
wg.Add(1)
go crawl(url, ch)
}
go func() {
wg.Wait() // 等待所有爬虫完成
close(ch) // 关闭通道
}()
var urlsCrawled []string
for u := range ch {
urlsCrawled = append(urlsCrawled, u)
}
elapsed := time.Since(start)
mut.Lock()
fmt.Printf("Crawled %d URLs in %s\n", len(urlsCrawled), elapsed)
mut.Unlock()
}
这个代码实例修复了原始代码的问题,并展示了如何使用Go语言的并发特性来实现一个简单的并发爬虫。通过使用sync.WaitGroup
来确保主goroutine等待所有爬虫任务完成,并通过sync.Mutex
来确保输出的线程安全。代码中还模拟了网络延迟,并且使用了通道来传递爬取的URL。
评论已关闭