【Go】Chromedp问题合集

无法获取iframe框架中的元素

https://github.com/chromedp/chromedp/issues/72

这个问题截止今日2022/10/20还没有被解决,这也是你要使用chromedp前需要考虑清楚的,如果含有嵌套结构chromedp是无法获取到子框架中的元素的!!!

判断元素是否存在

目前我发现的有三种方法:

  1. chromedp.Evaluate + document.querySelectorAll

chromedp.Evaluate(`document.querySelectorAll("#submit-mfa-btn").length`, &mailPageExist)

其中mailPageExist为[]byte类型可以从控制台看出,如果没有该元素则返回为0(string类型),有为1

  1. EvaluteAsDevTool

chromedp.EvaluateAsDevTools(`document.querySelector("body > div.bcapc-popup.bcap-popup.bcapc-popup-lang-en > div")`, &captchaExist)

用法和上面差不多,官方文档中说用这个命令是模拟在控制台中输入信息。如图有值返回js没值返回null

3.Nodes

这是问题check for an element is present in the page中官方给出的解答

chromedp.Nodes(yourSelector, &nodes, chromedp.AtLeast(0))

  1. chromedp.Evaluate + document.evaluate

这是问题xPath count get data中官方给出的解答

chromedp.Evaluate(`document.evaluate('count(//*[@id="country-additional-info"]/table/tbody/tr)', document).numberValue`, &additionalLen)

问题

有时候获得的结果很奇怪,明明没有这个元素但是有返回值,所以具体什么情况用什么还得自己试试。除此之外读取数据的时候记得转为string类型,因为[48]转换为字符串就是0

鼠标悬浮在指定元素

步骤:

  1. 获取想要悬浮元素的位置(x,y);
  2. 利用input.mousemoved将鼠标置于(x,y)处.
			chromedp.QueryAfter("#kyc-ui > div.style-dialog-body.css-1q3mrho > div.css-gnqbje > div > div > div.css-16vu25q > div.css-5dr7s > div > div.css-1wi4m92 > div > div > div.css-1ggy8dc", func(fctx context.Context, id runtime.ExecutionContextID, node ...*cdp.Node) error {
				n := node[0]
				return qrScreenshot(n, fctx)
			}),

func QrScreenshot(n *cdp.Node, cxt context.Context) error {
	boxes, err := dom.GetContentQuads().WithNodeID(n.NodeID).Do(cxt)
	if err != nil {
		return err
	}
	if len(boxes) == 0 {
		return chromedp.ErrInvalidDimensions
	}
	content := boxes[0]
	c := len(content)
	if c%2 != 0 || c < 1 {
		return chromedp.ErrInvalidDimensions
	}
	var x, y float64
	for i := 0; i < c; i += 2 {
		x += content[i]
		y += content[i+1]
	}
	x /= float64(c / 2)
	y /= float64(c / 2)
	p := &input.DispatchMouseEventParams{
		Type: input.MouseMoved,
		X:    x,
		Y:    y,
	}

	if err := p.Do(cxt); err != nil {
		return err
	}


	return p.Do(cxt)
}

cookie的设置和获取

cookie可以在控制台查看,这里也是利用DevTool中的GetAllCookies和SetCookies来获取和设置cookie

getCookies: https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-getCookies

setCookies: https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-setCookies

(PS: 这里介绍一款谷歌插件专门用于管理cookie的叫EditThisCookie,图标很可爱就是一个小饼干,可以通过这个插件查看cookie信息以及导入导出cookie)

获取cookie

其实重点就只有network.GetAllCookies().Do(ctx),这段代码是获取p20t和cr00两个cookie

func GetCookies(ctx context.Context) (string, string) {
	var cookie model.User
	coo, err := network.GetAllCookies().Do(ctx)
	if err != nil {
		fmt.Println(err)
		return "err", ""
	}
	for _, v := range coo {
		if v.Name == "p20t" {
			cookie.P20t = v.Value
		} else if v.Name == "cr00" {
			cookie.Cr00 = v.Value
		}
	}

	return cookie.P20t, cookie.Cr00
}

设置cookie

network.SetCookie(name, value),其他相关参数可以在控制台查看,DevTools手册中也有具体解释:https://chromedevtools.github.io/devtools-protocol/tot/Network/#method-setCookie

func SetCookies(name string, value string, domain string, httpOnly bool, secure bool, sameSite network.CookieSameSite) chromedp.Tasks {
	//创建一个chrome任务
	return chromedp.Tasks{
		//ActionFunc是一个适配器,允许使用普通函数作为操作。
		chromedp.ActionFunc(func(ctx context.Context) error {
			// 设置Cookie存活时间
			expr := cdp.TimeSinceEpoch(time.Now().Add(180 * 24 * time.Hour))
			// 添加Cookie到chrome
			//SetCookie使用给定的cookie数据设置一个cookie; 如果存在,可能会覆盖等效的cookie。
			err := network.SetCookie(name, value).
				// 设置cookie到期时间
				WithExpires(&expr).
				// 设置cookie作用的站点
				WithDomain(domain). //访问网站主体
				// 设置httponly,防止XSS攻击
				WithHTTPOnly(httpOnly).
				WithSameSite(sameSite).
				WithSecure(secure).
				//Do根据提供的上下文执行Network.setCookie。
				Do(ctx)
			if err != nil {
				return err
			}
			return nil
		}),
	}
}

保存cookie的其他办法

在opts中加入_<font style="color:#6272a4;">chromedp.UserDataDir("E:\\Go_workspace\\mouse-simulation\\cookie")</font>__,_这样浏览器将用户信息保存到一个文件夹中,下次再打开可以继承上一次的信息。加上这句话以后每次打开的浏览器就不再独立了!

获取div中的元素

这是chromedp的例子,我之前都没发现还找了好久嘤嘤嘤,这告诉我们要认真读文档。

https://github.com/chromedp/examples/blob/master/text/main.go

其实就一句话

chromedp.Text(.Documentation-overview, &res, chromedp.NodeVisible)

鼠标拖动(滑块验证)

go使用chromedp模拟滑动验证登录 - 逍遥03 - 博客园

//模拟滑动验证
chromedp.QueryAfter("body > div.bcapc-popup.bs-popup.bcapc-popup-lang-en > div > div.bs-content > div.verify-slider.bs-slide-container > div.bs-slide-thumb", func(fctx context.Context, id runtime.ExecutionContextID, node ...*cdp.Node) error {
        n := node[0]
        return MouseDragNode(n, fctx)
    }),


//鼠标拖拽滑块
func MouseDragNode(n *cdp.Node, cxt context.Context) error {
    boxes, err := dom.GetContentQuads().WithNodeID(n.NodeID).Do(cxt)
    if err != nil {
        return err
    }
    if len(boxes) == 0 {
        return chromedp.ErrInvalidDimensions
    }
    content := boxes[0]
    c := len(content)
    if c%2 != 0 || c < 1 {
        return chromedp.ErrInvalidDimensions
    }
    var x, y float64
    for i := 0; i < c; i += 2 {
        x += content[i]
        y += content[i+1]
    }
    x /= float64(c / 2)
    y /= float64(c / 2)

    p := &input.DispatchMouseEventParams{
        Type:       input.MousePressed,
        X:          x,
        Y:          y,
        Button:     input.Left,
        ClickCount: 1,
    }
    // 鼠标左键按下
    if err := p.Do(cxt); err != nil {
        return err
    }
    // 拖动
    p.Type = input.MouseMoved
    max := 450.0
    log.Println(p.X)
    for {
        if p.X > max {
            break
        }
        rt := rand.Intn(20) + 20
        chromedp.Run(cxt, chromedp.Sleep(time.Millisecond*time.Duration(rt)))
        x := rand.Intn(2) + 15
        y := rand.Intn(2)
        p.X = p.X + float64(x)
        p.Y = p.Y + float64(y)
        if err := p.Do(cxt); err != nil {
            return err
        }
    }
    // 鼠标松开
    p.Type = input.MouseReleased
    return p.Do(cxt)
}

打开浏览器权限

在编写网页自动化的过程中需要开摄像头这时会有弹窗让你选择是否给权限,弹窗是无法用chromedp完成点击操作的,因此我们需要设置让浏览器自动给该网页摄像头权限,这是我找到的几个相关问题的答案:

总结一下有两种方案:

  1. GrantPermissions

https://chromedevtools.github.io/devtools-protocol/tot/Browser/#method-grantPermissions

GrantPermissions有两个参数(最后一个俺也不知道干啥用的)

  • permissiontype有一下这些选项(由于没找到和摄像头相关的因此项目中没用这个方式)

https://chromedevtools.github.io/devtools-protocol/tot/Browser/#type-PermissionType

但是在https://github.com/chromedp/chromedp/issues/639中有人用下面的代码给权限,但是我试了没用

      browser.GrantPermissions([]browser.PermissionType {                          
       "audioCapture", "videoCapture",                                            
 }), 
  • WithOrigin填写弹框出现的网址,也就是会在这个网页范围内赋予权限,其他网站依旧拒绝。
browser.GrantPermissions([]browser.PermissionType{browser.PermissionTypeNotifications}).WithOrigin("https://github.com")
  1. SetPermission

https://chromedevtools.github.io/devtools-protocol/tot/Browser/#method-setPermission

SetPermission有三个参数,这里就拿项目中的代码为例,打开摄像头有两个权限,一个是照相,一个是麦克风

  • PermissionDescriptor对应权限列表:

https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/modules/permissions/permission_descriptor.idl

  • SetPermission有两个参数,一个就是PermissionDescriptor,另一个有<font style="color:#78dce8;">browser</font>._<font style="color:#9580ff;">PermissionSettingDenied</font>_<font style="color:#78dce8;">browser</font>._<font style="color:#9580ff;">PermissionSettingGranted</font>_两个选项
  • WithOrigin和上面一样
cameraPermission := browser.PermissionDescriptor{Name: "camera"}
microphonePermission := browser.PermissionDescriptor{Name: "microphone"}
browser.SetPermission(&cameraPermission, browser.PermissionSettingGranted).WithOrigin("https://accounts.binance.com/en/need-kyc")
browser.SetPermission(&microphonePermission, browser.PermissionSettingGranted).WithOrigin("https://accounts.binance.com/en/need-kyc")
		

新标签页聚焦

https://github.com/chromedp/chromedp/issues/965

从network中获取内容

https://github.com/chromedp/chromedp/issues/543

已经打开的浏览器中添加页面

要添加的页面通过websock连接对应浏览器

https://github.com/chromedp/chromedp/issues/1147

https://github.com/chromedp/chromedp/issues/1013

allocCtx, cancel := chromedp.NewRemoteAllocator(context.Background(), "ws://127.0.0.1:"+info.Port+"/")
	defer cancel()

已经打开的浏览器启动时监听端口–remote-debugging-port = 9222

chromedp.Flag("remote-debugging-port", info.Port),
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我有一个小脑瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值