用golang实现一个并发爬虫

在Go语言中实现一个并发爬虫,可以使用标准库中的`net/http`包来发送HTTP请求,使用`golang.org/x/net/html`包来解析HTML,以及使用`sync`包中的`WaitGroup`来同步并发的goroutines。下面是一个简单的并发爬虫示例,它会并发地访问网页,并打...

在Go语言中实现一个并发爬虫,可以使用标准库中的net/http包来发送HTTP请求,使用golang.org/x/net/html包来解析HTML,以及使用sync包中的WaitGroup来同步并发的goroutines。下面是一个简单的并发爬虫示例,它会并发地访问网页,并打印出网页中的所有链接。

package main

import (
	"fmt"
	"net/http"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
	"sync"
)

// 用于存储访问的URL
var urls = []string{
	"https://plumephp.com/posts/",
	"https://plumephp.com/about/",
	// 可以添加更多的URL
}

// 用于同步goroutines
var wg sync.WaitGroup

func main() {
	// 启动所有goroutines
	for _, url := range urls {
		wg.Add(1)
		go crawl(url)
	}

	// 等待所有goroutine完成
	wg.Wait()
}

// crawl 函数用于访问URL并打印出网页中的所有链接
func crawl(url string) {
	defer wg.Done()

	// 发送HTTP GET请求
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()

	// 解析HTML
	doc, err := html.Parse(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	// 遍历DOM树,查找所有的a标签
	forEachNode(doc, atom.A, func(n *html.Node) {
		// 获取href属性
		for _, a := range n.Attr {
			if a.Key == "href" {
				fmt.Println(a.Val)
			}
		}
	})
}

// forEachNode 函数遍历DOM树,查找指定的标签
func forEachNode(n *html.Node, tag atom.Atom, f func(*html.Node)) {
	if n.Type == html.ElementNode && n.DataAtom == tag {
		f(n)
	}
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		forEachNode(c, tag, f)
	}
}

代码解释:

  1. 我们定义了一个urls切片,里面包含了需要爬取的网页URL。
  2. 使用sync.WaitGroup来同步并发的goroutines。
  3. main函数中,我们遍历urls切片,为每个URL启动一个goroutine,并使用crawl函数来处理。
  4. crawl函数首先使用http.Get发送HTTP GET请求,然后使用html.Parse解析HTML。
  5. 使用forEachNode函数遍历DOM树,查找所有的<a>标签,并打印出它们的href属性值。
  6. forEachNode是一个递归函数,它查找指定的标签并执行提供的回调函数。

请注意,这个示例是一个基础的并发爬虫,实际使用中可能需要考虑更多的因素,比如错误处理、重试机制、用户代理设置、robots.txt协议遵守等。此外,对于大规模的爬虫项目,可能需要使用更高级的并发控制和调度机制。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页