【go语言】4.3.1 构建一个并发爬虫

162 阅读2分钟

在这个章节,我们将实现一个简单的并发网页爬虫。这个爬虫将会访问一个指定的网页并获取它的内容,然后找出所有链接,并并发地爬取这些链接。

首先,我们需要一个函数来获取网页的内容。我们将使用 net/http 包的 Get 函数来发送 HTTP 请求,并使用 io/ioutil 包的 ReadAll 函数来读取响应的内容:

func fetch(url string) (string, error) {
	resp, err := http.Get(url)
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	return string(body), nil
}

接下来,我们需要一个函数来从网页内容中提取链接。在这个例子中,我们将使用一个简单的正则表达式来匹配链接。在实际的应用中,你可能需要使用一个 HTML 解析库来更准确地提取链接:

func extractLinks(content string) []string {
	re := regexp.MustCompile(`href="(http://[^"]+)"`)
	matches := re.FindAllStringSubmatch(content, -1)

	links := make([]string, len(matches))
	for i, match := range matches {
		links[i] = match[1]
	}

	return links
}

然后,我们需要一个函数来并发地爬取链接。我们将使用一个 goroutine 来爬取每个链接,并使用一个 channel 来收集结果:

func crawl(links []string) []string {
	results := make(chan string)
	for _, link := range links {
		go func(link string) {
			content, err := fetch(link)
			if err == nil {
				results <- content
			}
		}(link)
	}

	contents := make([]string, len(links))
	for i := range contents {
		contents[i] = <-results
	}

	return contents
}

最后,我们需要一个函数来启动爬虫。这个函数将先获取初始网页的内容,然后提取链接,最后并发地爬取这些链接:

func startCrawler(url string) {
	content, err := fetch(url)
	if err != nil {
		fmt.Println(err)
		return
	}

	links := extractLinks(content)
	contents := crawl(links)

	for _, content := range contents {
		fmt.Println(content)
	}
}

注意,这个例子中的爬虫很简单,它并没有处理一些重要的问题,如链接去重、错误处理、限制并发数、遵守 robots.txt 等。在实际的应用中,你需要处理这些问题。

希望这个例子可以帮助你理解如何在 Go 中使用并发。并发是 Go 的一个重要特性,理解并熟练使用它可以帮助你编写更高效的程序。 推荐阅读:

mp.weixin.qq.com/s/dV2JzXfgj…

mp.weixin.qq.com/s/an83QZOWX…

file