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

huangapple go评论91阅读模式
英文:

How to access db while running a webdriver using chromedp?

问题

我想在银行页面上自动提交一次性密码(OTP)。只有在webdriver点击银行页面上的确认按钮后,我才能从数据库中获取OTP。确认后,我需要从数据库中获取OTP,然后自动提交OTP。

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

// 运行chromedp任务
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"]`),
    // 在下面执行获取OTP的操作,这里会报错
    otp := fetchOTPFromDb()
    chromedp.SendKeys(`//input[@type="password"]`, otp),
    chromedp.WaitVisible(`#confirmButton`),
    chromedp.Click(`#confirmButton`))
if err != nil {
    log.Fatal(err)
}

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

英文:

I want to automate OTP submission on a bank page. I will get the OTP in my database only after webdriver have clicked confirm on the bank page. After confirming, I need to fetch OTP from the db and then automate OTP submission.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

  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=&quot;Login&quot;]`),
		chromedp.WaitVisible(`#Go`),
		chromedp.Click(`#Go`),
		chromedp.WaitVisible(`#confirmButton`),
		chromedp.Click(`#confirmButton`),
		chromedp.WaitVisible(`//input[@type=&quot;password&quot;]`),
		// perform  fetch OTP below, this raise error
		otp := fetchOTPFromDb()
		chromedp.SendKeys(`//input[@type=&quot;password&quot;]`, otp),
		chromedp.WaitVisible(`#confirmButton`),
		chromedp.Click(`#confirmButton`))
	if err != nil {
		log.Fatal(err)
	}

<!-- end snippet -->

The problem is that chromedp.Run expects all args to be of the type chromedp.Tasks, so I can't call custom functions there and I get error while fetching the OTP from db. How do I go around this?

答案1

得分: 1

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

这样做是必需的,因为一次性密码在页面获取之前是不存在的,因此必须在操作资源时进行读取。

像这样

package main

import "context"

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

func (a OTPAction) Do(ctx context.Context) error {
	// 在这里获取OTP
	otp := "otp测试"
	return chromedp.SendKeys(`//input[@id="user-message"]`, otp).Do(ctx)
}
英文:

The solution is to wrap the otp fetch within an Action.Do call, then return the result of a call to chromdp.SendKeys to set the HTML input value.

It is required to work that way because the One Time Password does not exist until the page was fetched, thus, its read must happen while manipulating the resource.

Like this

package main

import &quot;context&quot;

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

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

huangapple
  • 本文由 发表于 2021年7月27日 01:29:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/68534169.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定