golang跨浏览器自动化控制插件库playwright-go的使用
Golang跨浏览器自动化控制插件库playwright-go的使用
Playwright是一个Go库,可以通过单一API自动化Chromium、Firefox和WebKit浏览器。Playwright旨在实现跨浏览器网页自动化,具有常青、强大、可靠和快速的特点。
支持的浏览器和平台
浏览器 | Linux | macOS | Windows |
---|---|---|---|
Chromium 136.0.7103.25 | ✅ | ✅ | ✅ |
WebKit 18.4 | ✅ | ✅ | ✅ |
Firefox 137.0 | ✅ | ✅ | ✅ |
所有平台上的所有浏览器都支持无头(headless)执行模式。
安装
安装playwright-go库:
go get -u github.com/playwright-community/playwright-go
安装Playwright驱动和浏览器(如果提供--with-deps
参数会同时安装操作系统依赖)。注意需要将版本号0.xxxx.x
替换为你当前go.mod
中使用的版本。每个次要版本升级都需要特定的Playwright驱动版本。
go run github.com/playwright-community/playwright-go/cmd/playwright@v0.xxxx.x install --with-deps
# 或者
go install github.com/playwright-community/playwright-go/cmd/playwright@v0.xxxx.x
playwright install --with-deps
或者,你也可以在代码中下载驱动和浏览器。但如果你的操作系统缺少这些浏览器依赖,仍然需要手动安装,因为安装系统依赖需要权限。
err := playwright.Install()
功能特性
Playwright旨在自动化单页应用(SPA)和渐进式网页应用(PWA)所使用的广泛且不断增长的网页浏览器功能:
- 跨多个页面、域名和iframe的场景
- 在执行操作(如点击、填充)前自动等待元素准备就绪
- 拦截网络活动以存根和模拟网络请求
- 模拟移动设备、地理位置、权限
- 通过shadow-piercing选择器支持Web组件
- 鼠标和键盘的原生输入事件
- 上传和下载文件
示例代码
以下示例爬取Hacker News当前最受欢迎的条目:
package main
import (
"fmt"
"log"
"github.com/playwright-community/playwright-go"
)
func main() {
pw, err := playwright.Run()
if err != nil {
log.Fatalf("could not start playwright: %v", err)
}
browser, err := pw.Chromium.Launch()
if err != nil {
log.Fatalf("could not launch browser: %v", err)
}
page, err := browser.NewPage()
if err != nil {
log.Fatalf("could not create page: %v", err)
}
if _, err = page.Goto("https://news.ycombinator.com"); err != nil {
log.Fatalf("could not goto: %v", err)
}
entries, err := page.Locator(".athing").All()
if err != nil {
log.Fatalf("could not get entries: %v", err)
}
for i, entry := range entries {
title, err := entry.Locator("td.title > span > a").TextContent()
if err != nil {
log.Fatalf("could not get text content: %v", err)
}
fmt.Printf("%d: %s\n", i+1, title)
}
if err = browser.Close(); err != nil {
log.Fatalf("could not close browser: %v", err)
}
if err = pw.Stop(); err != nil {
log.Fatalf("could not stop Playwright: %v", err)
}
}
更多示例
- 下载文件
- 网站端到端测试
- 在浏览器中执行JavaScript
- 模拟移动设备和地理位置
- 使用WaitGroup进行并行爬取
- 将网站渲染为PDF
- 爬取HackerNews
- 截图
- 录制视频
- 监控网络活动
工作原理
Playwright是一个Node.js库,它使用:
- Chrome DevTools协议与Chromium通信
- 补丁版Firefox与Firefox通信
- 补丁版WebKit与WebKit通信
这些补丁基于浏览器的原始源代码,不会修改浏览器行为,因此浏览器基本上与你在野外看到的相同。对不同编程语言的支持基于在Node.js领域公开RPC服务器,这允许其他语言使用Playwright而无需实现所有自定义逻辑。
Node.js和其他语言之间的桥梁基本上是一个与Playwright结合的Node.js运行时,为每种语言(约50MB)提供,然后通过stdio通信发送相关命令。这也会下载预编译的浏览器。
资源
- Playwright for Go文档
- Playwright文档
- 示例配方
更多关于golang跨浏览器自动化控制插件库playwright-go的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang跨浏览器自动化控制插件库playwright-go的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Playwright-go: Golang跨浏览器自动化控制库
Playwright-go是Microsoft Playwright的Golang绑定,它允许你通过代码自动化控制Chromium、Firefox和WebKit浏览器,实现端到端的测试和网页自动化操作。
安装Playwright-go
首先需要安装Playwright-go库:
go get github.com/playwright-community/playwright-go
然后安装所需的浏览器二进制文件:
go run github.com/playwright-community/playwright-go/cmd/playwright install
基本使用示例
1. 启动浏览器并访问页面
package main
import (
"log"
"github.com/playwright-community/playwright-go"
)
func main() {
pw, err := playwright.Run()
if err != nil {
log.Fatalf("could not start playwright: %v", err)
}
defer pw.Stop()
browser, err := pw.Chromium.Launch()
if err != nil {
log.Fatalf("could not launch browser: %v", err)
}
defer browser.Close()
page, err := browser.NewPage()
if err != nil {
log.Fatalf("could not create page: %v", err)
}
if _, err = page.Goto("https://example.com"); err != nil {
log.Fatalf("could not goto: %v", err)
}
title, err := page.Title()
if err != nil {
log.Fatalf("could not get title: %v", err)
}
log.Printf("Page title: %s", title)
}
2. 填写表单并提交
func fillForm() {
// ...前面的初始化代码同上...
page, err := browser.NewPage()
if err != nil {
log.Fatalf("could not create page: %v", err)
}
if _, err = page.Goto("https://example.com/login"); err != nil {
log.Fatalf("could not goto: %v", err)
}
// 填写用户名和密码
if err = page.Locator("#username").Fill("testuser"); err != nil {
log.Fatalf("could not fill username: %v", err)
}
if err = page.Locator("#password").Fill("password123"); err != nil {
log.Fatalf("could not fill password: %v", err)
}
// 点击登录按钮
if err = page.Locator("button[type='submit']").Click(); err != nil {
log.Fatalf("could not click submit button: %v", err)
}
// 等待导航完成
page.WaitForNavigation()
}
3. 截图和PDF生成
func takeScreenshotAndPDF() {
// ...初始化代码...
page, err := browser.NewPage()
if err != nil {
log.Fatalf("could not create page: %v", err)
}
if _, err = page.Goto("https://example.com"); err != nil {
log.Fatalf("could not goto: %v", err)
}
// 截图
if _, err = page.Screenshot(playwright.PageScreenshotOptions{
Path: playwright.String("screenshot.png"),
}); err != nil {
log.Fatalf("could not take screenshot: %v", err)
}
// 生成PDF
pdfData, err := page.PDF(playwright.PagePdfOptions{
Path: playwright.String("page.pdf"),
})
if err != nil {
log.Fatalf("could not generate PDF: %v", err)
}
log.Printf("Generated PDF with %d bytes", len(pdfData))
}
高级功能
1. 处理iframe
func handleIframe() {
// ...初始化代码...
page, err := browser.NewPage()
if err != nil {
log.Fatalf("could not create page: %v", err)
}
if _, err = page.Goto("https://example.com/iframe-page"); err != nil {
log.Fatalf("could not goto: %v", err)
}
// 获取iframe
frame := page.Frame("iframe-name")
if frame == nil {
frame = page.FrameByURL("https://example.com/iframe-content")
}
// 在iframe内操作
if frame != nil {
if err = frame.Locator("#iframe-button").Click(); err != nil {
log.Fatalf("could not click iframe button: %v", err)
}
}
}
2. 模拟移动设备
func emulateMobile() {
// ...初始化代码...
iphone := playwright.Devices["iPhone 11"]
context, err := browser.NewContext(playwright.BrowserNewContextOptions{
Viewport: iphone.Viewport,
UserAgent: iphone.UserAgent,
DeviceScaleFactor: iphone.DeviceScaleFactor,
IsMobile: iphone.IsMobile,
HasTouch: iphone.HasTouch,
})
if err != nil {
log.Fatalf("could not create context: %v", err)
}
defer context.Close()
page, err := context.NewPage()
if err != nil {
log.Fatalf("could not create page: %v", err)
}
if _, err = page.Goto("https://example.com"); err != nil {
log.Fatalf("could not goto: %v", err)
}
}
3. 网络拦截和模拟
func interceptRequests() {
// ...初始化代码...
page, err := browser.NewPage()
if err != nil {
log.Fatalf("could not create page: %v", err)
}
// 拦截所有请求
err = page.Route("**/*", func(route playwright.Route) {
// 屏蔽图片请求
if route.Request().ResourceType() == "image" {
route.Abort()
} else {
route.Continue()
}
})
if err != nil {
log.Fatalf("could not set up route: %v", err)
}
if _, err = page.Goto("https://example.com"); err != nil {
log.Fatalf("could not goto: %v", err)
}
}
测试示例
Playwright-go非常适合用于端到端测试:
func TestLogin(t *testing.T) {
pw, err := playwright.Run()
if err != nil {
t.Fatalf("could not start playwright: %v", err)
}
defer pw.Stop()
browser, err := pw.Chromium.Launch()
if err != nil {
t.Fatalf("could not launch browser: %v", err)
}
defer browser.Close()
page, err := browser.NewPage()
if err != nil {
t.Fatalf("could not create page: %v", err)
}
if _, err = page.Goto("http://localhost:8080/login"); err != nil {
t.Fatalf("could not goto: %v", err)
}
// 测试登录流程
if err = page.Locator("#username").Fill("testuser"); err != nil {
t.Fatalf("could not fill username: %v", err)
}
if err = page.Locator("#password").Fill("password123"); err != nil {
t.Fatalf("could not fill password: %v", err)
}
if err = page.Locator("button[type='submit']").Click(); err != nil {
t.Fatalf("could not click submit button: %v", err)
}
// 验证登录成功
if _, err = page.WaitForSelector(".welcome-message"); err != nil {
t.Fatalf("login failed: %v", err)
}
}
总结
Playwright-go提供了强大的跨浏览器自动化能力,主要特点包括:
- 支持Chromium、Firefox和WebKit
- 自动等待元素出现和可操作状态
- 强大的选择器和定位器API
- 网络拦截和模拟功能
- 设备模拟和移动端测试
- 截图和PDF生成
相比传统的Selenium方案,Playwright-go具有更好的性能和更现代的API设计,非常适合用于自动化测试和网页抓取等场景。