Golang Go语言中 Goroutine 如何并行抓取网页
在写一道公司的题目,完成一个爬虫,题目要求之一是
要求支持多 routine 并行抓取(注意:这里并不是指简单设置 GOMAXPROCS>1)
然后我就懵了,怎么样才是并行抓取?我现在只知道设置 runtime.GOMAXPROCS=N
设置 GOMAXPROCS 是并行抓取吗,为什么?
不是很明白出题人的意思...
Golang Go语言中 Goroutine 如何并行抓取网页
就是写个任务调度框架吧😂
更多关于Golang Go语言中 Goroutine 如何并行抓取网页的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
- 这个 IO 密集型, 像 Node.js 这样单进程也可以完成的很好, Promise.map + concurrency
2. golang: https://github.com/magicdawn/go-co/tree/master 用 task.map
https://github.com/magicdawn/go-co/blob/master/task/map.go#L11
你的意思是: 可以提交很多个 routine, 然后设置 runtime.GOMAXPROCS=cpu 核心数, 但是这样是不行的, 会导致所有的 routine 都进行了 request
题目意思可能是: 只有那么几个 concurrency routine 在跑, 一个结束了, 开始处理新的
前面那一种是相当于 concurrency = Infinity
应该是想说 worker pool 吧?
https://gobyexample.com/worker-pools
我是这么想的 我只开 8 个 routine,不停的从 channel/queue 里面读抓取的网址然后去爬它.
但是如果我不开 GOMAXPROCS,那么每一个瞬间,都最多只有一个 routine 在跑,这只是利用异步 IO 在并发.
但是只要我设置了 GOMAXPROCS,这些 routine 就会被调度到不同的线程->不同的 CPU,这样才是并行
所以这里并行的关键是设置 GOMAXPROCS 对吧,那题目说的不是简单设置 GOMAXPROCS,这才是让我困惑的地方,我以为有什么其他的方法来实现并行
开 N 个 gorutine ,读 chan 里的任务,就这么简单,什么第三方库都不用。
这么基础的东西还要来 V2EX 问?贵司心略宽啊。
不用管 GOMAXPROCS 的事,默认是 cpu 核数,会用上所有核心的了
对于有限长度的队列, 如 []int{ 1, 2, 3, 4 }
job 为 sleep i 秒, 使用并发为 2 的时候, 耗时为 6s(2 + 4)
https://github.com/magicdawn/go-co/blob/master/demo/map/main.go
长度变化的队列, 工作中碰到的都是
while true
拿出 1000 个
等待 1000 个以某个并发完成
continue
再不行, 将 async.parallelLimit 代码抄下来写一点
啊, 这种还是 nodejs 来的简单…
关于 GOMAXPROCS,版本不到 1.5
我厂有国内流量最大的 Go 项目
百度吧?
我的意思是,为什么你这都不会写还……
lz 的意思是,并行的关键就是简单设置 GOMAXPROCS ,你怎么看出来不会写
“爬虫: Goroutine 如何并行抓取网页”
“然后我就懵了,怎么样才是并行抓取?我现在只知道设置 runtime.GOMAXPROCS=N ”
我现在只知道设置
我现在只知道设置
我现在只知道设置
我是这样看出来不会写的。
就爬虫这个例子,不论 GOMAXPROCS 是 1 还是几,都能写出并行抓取的爬虫,因为主要工作都是 net poller 做的, goroutine 并不需要多少 cpu 时间片。
主要工作是网络 io 的场景, GOMAXPROCS 和并行没有关系。
楼主还不知道并发并行的区别
一年多前自己的实现是 buffer chan
在Go语言中,Goroutine 是实现并发执行的有效工具。要并行抓取网页,你可以利用 Goroutine 的轻量级和高效性,结合 net/http
包来发送 HTTP 请求。以下是一个简单的示例,展示了如何使用 Goroutine 并行抓取网页:
-
定义一个函数来抓取网页:这个函数会接收一个 URL,使用
http.Get
方法发送请求,并返回响应体内容。 -
使用 Goroutine 并行执行:在需要并行抓取的 URL 列表上迭代,为每个 URL 启动一个 Goroutine。
-
等待所有 Goroutine 完成:使用
sync.WaitGroup
来确保所有 Goroutine 在主函数退出前完成。
示例代码:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"sync"
)
func fetchURL(url string, wg *sync.WaitGroup, results chan<- string) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
results <- fmt.Sprintf("Failed to fetch %s: %v", url, err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
results <- fmt.Sprintf("Failed to read %s: %v", url, err)
return
}
results <- string(body)
}
func main() {
// URL 列表和 WaitGroup 初始化代码省略...
// 使用 Goroutine 和 channel 收集结果...
}
这样,你就可以利用 Goroutine 的并发特性,高效地并行抓取多个网页。注意,实际应用中应添加错误处理、超时控制等,以提高程序的健壮性。