golang自动化浏览器测试与驱动插件库chromedp的使用

golang自动化浏览器测试与驱动插件库chromedp的使用

关于chromedp

chromedp包是一个更快、更简单的方式,用于在Go中驱动支持Chrome DevTools协议的浏览器,无需外部依赖。

安装

使用常规的Go安装方式:

$ go get -u github.com/chromedp/chromedp

示例

以下是一个完整的chromedp使用示例,演示如何打开网页并获取页面标题:

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/chromedp/chromedp"
)

func main() {
	// 创建上下文
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// 设置超时时间
	ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
	defer cancel()

	// 定义变量来存储页面标题
	var title string

	// 执行浏览器操作
	err := chromedp.Run(ctx,
		// 导航到网页
		chromedp.Navigate("https://www.example.com"),
		// 等待页面加载
		chromedp.Sleep(2*time.Second),
		// 获取页面标题
		chromedp.Title(&title),
	)
	if err != nil {
		log.Fatal(err)
	}

	// 打印页面标题
	fmt.Printf("Page title: %s\n", title)
}

常见问题解答

问题:我看不到任何Chrome浏览器窗口

默认情况下,Chrome以无头模式运行。可以通过覆盖默认选项来显示浏览器窗口:

opts := append(chromedp.DefaultExecAllocatorOptions[:],
	chromedp.Flag("headless", false),
)
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()

ctx, cancel := chromedp.NewContext(allocCtx)
defer cancel()

问题:我看到"context canceled"错误

当与浏览器的连接丢失时,chromedp会取消上下文,可能导致此错误。例如,如果手动关闭浏览器或浏览器进程被终止。

问题:Chrome在我的Go程序结束时立即退出

在Linux上,chromedp配置为避免资源泄漏,会强制终止任何启动的Chrome子进程。如果需要启动长时间运行的Chrome实例,可以手动启动Chrome并使用RemoteAllocator连接。

问题:不使用Run执行操作会导致"invalid context"

默认情况下,chromedp上下文没有执行器,可以手动指定:

ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
chromedp.Run(ctx, chromedp.ActionFunc(func(ctx context.Context) error {
	_, err := domain.SomeAction().Do(ctx)
	return err
}))

问题:我想在无头环境中使用chromedp

最简单的方法是使用chromedp/headless-shell镜像运行Go程序,该镜像包含headless-shell,一个更小的Chrome无头构建。


更多关于golang自动化浏览器测试与驱动插件库chromedp的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang自动化浏览器测试与驱动插件库chromedp的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang自动化浏览器测试与chromedp使用指南

chromedp是一个强大的Golang库,用于通过Chrome DevTools协议(CDP)控制Chrome或Chromium浏览器,非常适合自动化测试和网页抓取场景。

安装chromedp

首先安装chromedp及其依赖:

go get -u github.com/chromedp/chromedp

基本用法示例

package main

import (
	"context"
	"log"
	"time"

	"github.com/chromedp/chromedp"
)

func main() {
	// 创建上下文
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// 设置超时
	ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
	defer cancel()

	// 定义变量存储结果
	var title, content string

	// 运行任务
	err := chromedp.Run(ctx,
		// 导航到页面
		chromedp.Navigate("https://example.com"),
		// 等待元素可见
		chromedp.WaitVisible("body"),
		// 获取页面标题
		chromedp.Title(&title),
		// 获取h1元素内容
		chromedp.Text("h1", &content, chromedp.NodeVisible),
	)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Title: %s", title)
	log.Printf("Content: %s", content)
}

核心功能

1. 元素选择与操作

// 点击元素
chromedp.Click("#submit-button", chromedp.NodeVisible),

// 输入文本
chromedp.SendKeys("#username", "myusername", chromedp.NodeVisible),

// 获取属性值
var href string
chromedp.AttributeValue("a.link", "href", &href, nil),

2. 等待策略

// 等待元素出现
chromedp.WaitVisible("#loading", chromedp.ByID),

// 等待元素消失
chromedp.WaitNotPresent("#spinner"),

// 自定义等待
chromedp.WaitFunc(func(ctx context.Context) error {
    // 自定义等待逻辑
    return nil
}),

3. 截图与PDF

// 截取整个页面
var buf []byte
chromedp.FullScreenshot(&buf, 90),

// 截取特定元素
chromedp.Screenshot("#banner", &buf, chromedp.NodeVisible),

// 生成PDF
chromedp.PrintToPDF(&buf, chromedp.WithLandscape(true)),

高级配置

自定义浏览器选项

opts := append(chromedp.DefaultExecAllocatorOptions[:],
    chromedp.Flag("headless", false),          // 显示浏览器窗口
    chromedp.Flag("disable-gpu", true),        // 禁用GPU加速
    chromedp.Flag("no-sandbox", true),         // 禁用沙箱
    chromedp.Flag("ignore-certificate-errors", true), // 忽略证书错误
)

allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
defer cancel()

ctx, cancel := chromedp.NewContext(allocCtx)
defer cancel()

处理弹窗和对话框

chromedp.ListenTarget(ctx, func(ev interface{}) {
    if _, ok := ev.(*page.EventJavascriptDialogOpening); ok {
        go func() {
            // 自动接受弹窗
            _ = chromedp.Run(ctx, page.HandleJavaScriptDialog(true))
        }()
    }
}),

实际测试示例

func TestLogin(t *testing.T) {
    ctx, cancel := chromedp.NewContext(context.Background())
    defer cancel()

    err := chromedp.Run(ctx,
        chromedp.Navigate("https://example.com/login"),
        chromedp.WaitVisible("#login-form"),
        chromedp.SendKeys("#username", "testuser"),
        chromedp.SendKeys("#password", "password123"),
        chromedp.Click("#submit"),
        chromedp.WaitVisible("#dashboard"),
    )
    
    if err != nil {
        t.Fatalf("测试失败: %v", err)
    }
}

性能优化建议

  1. 复用浏览器实例而不是为每个测试创建新实例
  2. 使用chromedp.NewRemoteAllocator连接已运行的浏览器实例
  3. 合理设置超时时间
  4. 避免不必要的截图和等待

chromedp提供了丰富的API可以满足大多数自动化测试需求,结合Golang的测试框架可以构建强大的浏览器自动化测试套件。

回到顶部