使用 Go-Rod 构建浏览器渲染池:一份全面的中文指南

简介

go-rod 是一个功能强大的 Go 语言库,用于通过 DevTools 协议驱动浏览器。它使得网页自动化、爬虫、端到端测试等任务变得简单高效。本文档在原有笔记的基础上,结合官方文档,提供一份更全面、更详细的 go-rod 使用指南。

核心概念

  • 浏览器(Browser): go-rod 可以启动和连接到一个浏览器实例,无论是本地安装的 Chrome,还是远程的 Docker 容器。
  • 页面(Page): 在一个浏览器实例中,可以创建一个或多个页面。每个页面都是一个独立的浏览上下文,可以加载不同的 URL。
  • 启动器(Launcher): go-rod 提供了 launcher 模块,用于方便地管理浏览器的启动和连接,包括远程连接和 Docker 容器。

安装与设置

1. 运行 Docker 镜像

为了方便和隔离,推荐使用官方提供的 Docker 镜像。这可以避免在本地安装 Chrome,并确保环境的一致性。

1
docker run -p 7317:7317 --rm ghcr.io/go-rod/rod

这条命令会启动一个 go-rod 容器,并将容器的 7317 端口映射到主机的 7317 端口。--rm 参数表示容器停止后自动删除。

2. 连接到正在运行的 Docker 容器

在你的 Go 代码中,你可以使用 launcher 来连接到这个正在运行的容器。

注意: 连接前请确保关闭了全局代理或隧道代理,否则可能会导致连接失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
"fmt"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/launcher"
)

func main() {
// 创建一个到远程 Docker 容器的连接
l := launcher.MustNewManaged("ws://127.0.0.1:7317")

// 在启动远程浏览器之前,可以设置一些启动参数
// 可用参数列表: https://peter.sh/experiments/chromium-command-line-switches/
l.Set("disable-gpu") // 禁用 GPU 加速

// 以有头模式启动
l.Headless(false)

// 连接到浏览器
browser := rod.New().Client(l.MustClient()).MustConnect()

// 在浏览器中打开一个新页面并获取标题
page := browser.MustPage("https://www.baidu.com")
title := page.MustEval("() => document.title")
fmt.Println(title)
}

常用功能

1. 截图

go-rod 可以轻松地对页面进行截图。

1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import (
"github.com/go-rod/rod"
"time"
)

func main() {
page := rod.New().NoDefaultDevice().MustConnect().MustPage("https://www.wikipedia.org/")
page.MustWindowFullscreen() // 窗口最大化
page.MustWaitStable().MustScreenshot("wikipedia.png") // 等待页面稳定后截图
time.Sleep(time.Hour)
}

2. 启动监控窗口

go-rod 提供了一个非常实用的功能:启动一个 web 窗口来实时监控浏览器中发生的事情。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"fmt"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/launcher"
"time"
)

func main() {
l := launcher.MustNewManaged("ws://127.0.0.1:7317")
browser := rod.New().Client(l.MustClient()).MustConnect()

// 启动一个服务来监控远程浏览器的截图
launcher.Open(browser.ServeMonitor(""))

fmt.Println(
browser.MustPage("https://www.baidu.com").MustEval("() => document.title"),
)
time.Sleep(time.Hour)
}

构建浏览器渲染池

对于需要处理大量渲染任务的场景,可以使用 go-rod 的页面池(Page Pool)来提高效率。页面池可以复用页面对象,避免了频繁创建和销毁页面的开销。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/launcher"
)

func main() {
l := launcher.MustNewManaged("ws://127.0.0.1:7317")
browser := rod.New().Client(l.MustClient()).MustConnect()

// 创建一个容量为 10 的页面池
pool := rod.NewPagePool(10)

// 定义页面创建函数
create := func() *rod.Page {
// 使用 MustIncognito 来隔离每个页面的会话
return browser.MustIncognito().MustPage()
}

urlList := []string{
"http://www.baidu.com",
"http://www.bing.com",
}

for _, url := range urlList {
// 从池中获取一个页面
page := pool.Get(create)

page.MustNavigate(url).MustWaitLoad()
println(page.MustInfo().Title)

// 将页面放回池中
pool.Put(page)
}
}

直接使用 Debug 端口

除了通过 7317 端口,go-rod 还可以直接连接到 Chrome 的远程调试端口(默认为 9222)。

1. 启动 Docker 容器并暴露调试端口

1
docker run -p 9222:9222 --rm ghcr.io/go-rod/rod:arm chrome --headless --no-sandbox --remote-debugging-port=9222 --remote-debugging-address=0.0.0.0

2. 在 Go 代码中连接到调试端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/launcher"
)

func main() {
container := launcher.MustResolveURL("ws://127.0.0.1:9222")
browser := rod.New().ControlURL(container).MustConnect()

pool := rod.NewPagePool(10)
create := func() *rod.Page {
return browser.MustIncognito().MustPage()
}

urlList := []string{
"http://www.baidu.com",
"http://www.bing.com",
}

page := pool.Get(create)

for _, url := range urlList {
page.MustNavigate(url).MustWaitLoad()
println(page.MustInfo().Title)
}

pool.Put(page)
}

https://kingjem.github.io/2025/06/29/go-rod-guide-cn/
作者
Ruhai
发布于
2025年6月29日
许可协议