《Go官方指南》练习:Web 爬虫

本文介绍了一个使用Go语言并发特性的Web爬虫练习。通过建立一个队列模拟广度优先搜索,利用map存储已抓取URL并解决并发安全性问题。详细讨论了为何选择map而非数组,以及如何通过计数器管理管道空状态,确保爬虫正确停止。
摘要由CSDN通过智能技术生成

题目:

练习:Web 爬虫

在这个练习中,我们将会使用 Go 的并发特性来并行化一个 Web 爬虫。

修改 Crawl 函数来并行地抓取 URL,并且保证不重复。

提示:你可以用一个 map 来缓存已经获取的 URL,但是要注意 map 本身并不是并发安全的!

思路:

借鉴利用队列实现广度优先算法的思路,把第一个url当做根节点,根节点下面的url当做孩子节点,队列当做管道。

  • 把第一个url作为根节点,查询[showCrawl()函数]
  • 将对应孩子节点集合加入管道。
  • 遍历这个孩子节点集合
  • 重复2~3步骤
  • 直到管道中没有元素

实现:

  1. (完整代码见最后面)
  2. 一些关键性问题在本代码后面
// Crawl 使用 fetcher 从某个 URL 开始递归的爬取页面,直到达到最大深度。
func Crawl(url string, depth int, fetcher Fetcher) {
   
	// 初始化工作
	if depth < 1 {
   
		return
	}
	Urls := make(chan []string, 10)  //相当于队列
	go showCrawl(url, Urls, fetcher) // 根节点遍历
	flag := 1                        // 用于探测管道中还有多少个元素

	// 2. 根据要求的深度(depth)查询 : 向下查询多少层
	for i := depth; i > 0; i-- {
   
		// 只要管道里有元素,就读取
		if flag > 0 {
   
			urls := <- Urls // urls == []string
			flag--                     // 管道元素数量--
			for _, url := range urls {
    // 一个页面下的url集合
				fmt.Printf("接收到的url:%s\n", url)
				if _, ok := store[url]; !ok {
    // 判断是否查询过
					go showCrawl(url, Urls, fetcher)
					flag++ 
				}
			}

		}
	}

查询函数:

// 查询页面,并将页面下的url放到管道中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值