如何在使用 chromedp 运行 webdriver 时访问数据库?

问题描述

我想在银行页面自动提交 OTP。只有在 webdriver 单击银行页面上的确认后,我才会在我的数据库获取 OTP。确认后,我需要从数据库获取OTP,然后自动提交OTP。

  ctx,cancel := chromedp.NewContext(context.Background(),chromedp.WithDebugf(log.Printf))
    defer cancel()

    // run chromedp tasks
    err := chromedp.Run(ctx,chromedp.Navigate(bankUrl),chromedp.WaitVisible(`#username`),chromedp.SendKeys(`#username`,`usernameXXX`),chromedp.WaitVisible(`#label2`,),chromedp.SendKeys(`#label2`,`passwordxxx` ),chromedp.Click(`//input[@title="Login"]`),chromedp.WaitVisible(`#Go`),chromedp.Click(`#Go`),chromedp.WaitVisible(`#confirmButton`),chromedp.Click(`#confirmButton`),chromedp.WaitVisible(`//input[@type="password"]`),// perform  fetch OTP below,this raise error
        otp := fetchOTPFromDb()
        chromedp.SendKeys(`//input[@type="password"]`,otp),chromedp.Click(`#confirmButton`))
    if err != nil {
        log.Fatal(err)
    }

问题是 chromedp.Run 期望所有 args 都是 chromedp.Tasks 类型,所以我无法在那里调用自定义函数,并且在从 db 获取 OTP 时出错。我该如何解决这个问题?

解决方法

解决方案是将 otp fetch 包装在 Action.Do 调用中,然后将调用结果返回到 chromdp.SendKeys 以设置 HTML 输入值。

必须以这种方式工作,因为在获取页面之前,一次性密码不存在,因此,必须在操作资源时进行读取。

像这样

package main

import "context"

type OTPAction struct {
    // DB ....
}

func (a OTPAction) Do(ctx context.Context) error {
    // fetch OTP here
    otp := "otp test"
    return chromedp.SendKeys(`//input[@id="user-message"]`,otp).Do(ctx)
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...