我正在进行golang之旅并进行最后一次练习,以便将Web爬虫更改为并行爬行而不是重复爬行(http://tour.golang.org/#73).我所改变的只是爬行功能.
var used = make(map[string]bool)
func Crawl(url string, depth int, fetcher Fetcher) {
if depth <= 0 {
return
}
body, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("\nfound: %s %q\n\n", url, body)
for _,u := range urls {
if used[u] == false {
used[u] = true
Crawl(u, depth-1, fetcher)
}
}
return
}
Run Code Online (Sandbox Code Playgroud)
为了使它并发,我在函数Crawl的调用之前添加了go命令,但是不是递归地调用Crawl函数,程序只找到" http://golang.org/ "页面而没有其他页面.
当我将go命令添加到函数Crawl的调用时,为什么程序不能正常工作?
问题似乎是,在爬网程序可以跟踪所有URL之前,您的进程正在退出.由于并发性,main()程序在工作人员完成之前退出.
为了避免这种情况,您可以使用sync.WaitGroup:
func Crawl(url string, depth int, fetcher Fetcher, wg *sync.WaitGroup) {
defer wg.Done()
if depth <= 0 {
return
}
body, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("\nfound: %s %q\n\n", url, body)
for _,u := range urls {
if used[u] == false {
used[u] = true
wg.Add(1)
go Crawl(u, depth-1, fetcher, wg)
}
}
return
}
Run Code Online (Sandbox Code Playgroud)
并呼吁Crawl在main如下:
func main() {
wg := &sync.WaitGroup{}
Crawl("http://golang.org/", 4, fetcher, wg)
wg.Wait()
}
Run Code Online (Sandbox Code Playgroud)
另外,不要依赖地图是线程安全的.
| 归档时间: |
|
| 查看次数: |
3337 次 |
| 最近记录: |