071-并发爬虫(二)

news/2024/11/8 15:03:25/

学习从来都不是一件困难的事情。那为啥我们学习会如此痛苦?其实难在坚持。这就好比跑步并不是一件困难的事,但是难在十年如一日的坚持。

如果你仔细一点,会发现我的 csdn 头像是《海贼王》这部动漫的主角头像。海贼王这部动漫从 1997 年开始连载,至今已经连载 21 年了。将一部作品连载至今,需要的不仅仅是智慧,更多的是毅力。

如果我们学习也能如此,日复一日,年复一年,我想也应该能有所成就吧。

废话不多说,我们接上一篇的话题,如何控制 goroutine 的并发度呢?总的来说,有两种办法,待会你会看到。

1. 使用 channel 控制并发度

上一篇我们写的代码本身没有错,但错在无穷无尽的并发会对系统造成影响,这会耗尽系统的文件描述符。一个解决办法就是控制最高并发度。

我们的程序从 url “池子”每拿到一个 url 就开启一个 goroutine,如果池子里的 url 数量非常大,一个不小心就能开启上万个 goroutine,我们希望能得到控制。

  • 使用 channel 占位控制并发度

假设我们限制 20 并发,怎么做?一个简单的做法就是每开启一个 goroutine 前,就向 channel 里放入一个占位标记,当 goroutine 运行结束后,就把占位标记移除。由于 channel 的缓冲区是固定的,一旦 channel 被占满,就再也无法开启新的 goroutine,除非有旧的 goutine 运行结束,并将 channel 中的标记删除。伪代码如下:

// tokens 是一个大小为 20 的 channel
tokens := make(chan struct{}, 20)
for {tokens <- struct{}{}go f()<-tokens
}

上面的程序就能控制同时最多 20 个 goroutine 运行。

  • 使用固定数量的 long-lived goroutine 控制并发度

另一种控制并发度的方法,是使用 long-lived goroutine,即长时间存活的 goroutine(简称长活协程),这有点像我们以前常说的线程池,在这里你可以说叫协程池。伪代码如下:

tasks := make(chan Type)
for i := 0; i < 20; i++ {go func() {for task := tasks {run(task)}}
}

有经验的同学一看就能知道,这是一个 producter-consumer 模型,即生产者消费者模型。生产者源源不断的将待执行的任务丢入缓冲区 tasks,而消费者(我们开启的 20 个 long-lived goroutine) 源源不断的消费缓冲区的任务。

上面这两种方法各有千秋,下面是具体的程序。

2. 程序

下面的两份代码都在 gopl/goroutine/concurrence 目录下面。

2.1 使用 channel 控制并发

package mainimport ("fmt""gopl/goroutine/link""log""os"
)var tokens = make(chan struct{}, 20)func crawl(url string) []string {fmt.Println(url)// 占位tokens <- struct{}{}urls, err := link.ExtractLinks(url)// 移除占位标记<-tokensif err != nil {log.Print(fmt.Sprintf("\x1b[31m%v\x1b[0m", err))}return urls
}func main() {if len(os.Args) < 2 {fmt.Println("Usage:\n\tgo run crawl.go <url>")os.Exit(1)}workList := make(chan []string)seen := make(map[string]bool)var n intn++go func() {workList <- os.Args[1:]}()for ; n > 0; n-- {list := <-workListfor _, url := range list {if seen[url] {continue}n++seen[url] = truego func(url string) {workList <- crawl(url)}(url)}}
}

2.2 使用 long-lived goroutine

package mainimport ("fmt""gopl/goroutine/link""log""os"
)func crawl(url string) []string {fmt.Println(url)urls, err := link.ExtractLinks(url)if err != nil {log.Print(fmt.Sprintf("\x1b[31m%v\x1b[0m", err))}return urls
}func main() {if len(os.Args) < 2 {fmt.Println("Usage:\n\tgo run crawl.go <url>")os.Exit(1)}workList := make(chan []string)unseenLinks := make(chan string)seen := make(map[string]bool)var n intn++go func() {workList <- os.Args[1:]}()// 开启 20 个固定的 long-lived goroutinefor i := 0; i < 20; i++ {go func() {for url := range unseenLinks {urls := crawl(url)go func() { workList <- urls }()}}()}for list := range workList {for _, url := range list {if seen[url] {continue}unseenLinks <- url}}
}

如此一来,你就可以再次运行上面的代码,就不会出现之前的 too many open files 的问题了。运行方法还是和上一篇一样,赶紧试试吧。

3. 总结

  • 掌握控制并发度的方法

http://www.ppmy.cn/news/709581.html

相关文章

李纳斯是个怎样的人?

我对生命的意义有种理论。我们可以在第一章里对人们解释生命的意义何在。这样可以吸引住他们。一旦他们被吸引住&#xff0c;并且付钱买了书&#xff0c;剩下的章节里我们就可以胡扯了。 虽然李纳斯戏谑的称自己是在胡扯&#xff0c;但是如果你看到后面&#xff0c;了解李纳斯…

被 KPI 绑架的百度贴吧

阅读本文大概需要 2.1 分钟。 你有一段不堪回首的往事吗&#xff1f; 可能有的人有&#xff0c;有的人没有。但于百度而言&#xff0c;这段往事想必与百度贴吧相关。 据易观千帆数据显示&#xff0c;短短 5 年时间&#xff0c;百度贴吧流失了近九成用户。 图数据源于易观千帆 …

千图成像python_【Python还能干嘛】爬取微信好友头像完成马赛克拼图(千图成像)~...

马赛克拼图 何谓马赛克拼图(千图成像)&#xff0c;简单来说就是将若干小图片平凑成为一张大图&#xff0c;如下图路飞一样&#xff0c;如果放大看你会发现里面都是一些海贼王里面的图片。 Our Tragets 爬取所有微信好友的头像&#x1f57a;&#x1f3fb;&#x1f57a;&#x1f…

用 python 快速「卡通化」人物头像

大家好&#xff0c;我是天作。 这个项目让我想起了以前玩QQ秀的时光。有了这个项目&#xff0c;再也不用找同学了&#xff0c;我自己也可以把头像卡通化了。 该项目为小视科技卡通肖像探索项目。可使用微信扫描下方二维码或搜索“AI卡通秀”小程序体验卡通化效果。 项目地址&am…

【Python】爬取微信好友头像完成马赛克拼图~

代码已重新整理上传到了我的KLab&#xff0c;为了更好的阅读体验可点击&#x1f517;【千图成像】爬取微信好友头像完成马赛克拼图&#x1f9e9;查看&#xff5e; 马赛克拼图 何谓马赛克拼图&#xff08;千图成像&#xff09;&#xff0c;简单来说就是将若干小图片平凑成为一…

【PyTorch】12 生成对抗网络实战——用GAN生成动漫头像

GAN 生成动漫头像 1. 获取数据2. 用GAN生成2.1 Generator2.2 Discriminator2.3 其它细节2.4 训练思路 3. 全部代码4. 结果展示与分析小结 深度卷积生成对抗网络&#xff08;DCGAN&#xff09;:Unsupervised Representation Learning with Deep Convolutional Generative Advers…

航海王燃烧意志服务器响应格式非法,航海王燃烧意志充值异常怎么处理 航海王燃烧意志充值异常申诉方法_斗蟹游戏网...

【斗蟹-航海王燃烧意志】航海王燃烧意志游戏中玩家在充值后发现没有到账&#xff0c;那要在怎么处理充值异常&#xff0c;下面小编带大家一起看看航海王燃烧意志充值异常申诉方法&#xff0c;希望能在游戏中帮到大家。 在航海王燃烧意志手游中&#xff0c;不少朋友在充值后彩钻…

这顶海贼王的帽子,我Python给你带上了 | 【人脸识别应用】

微信公众号&#xff1a;AI算法与图像处理如果你觉得对你有帮助&#xff0c;欢迎分享和转发哈 https://zhuanlan.zhihu.com/p/32299758?utm_sourcewechat_session&utm_mediumsocial&utm_oi704056637840695296 内容目录 故事起因思路与实现准备工作详细代码和效果总结1.…