问题描述
我想在银行页面上自动提交 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)
}