如何使用golang knq / chromedp检查页面中是否存在元素

I am creating an app to using [chromedp][1]

How can I check for an element is present in the page?

I tried to use cdp.WaitVisible() but it didn't give me what I wanted.

I need this so I can make dictions if the application will do one thing or the other.

For this example, suppose I need to know if the search input is present or not

How can I do that?

[1]: https://github.com/knq/chromedp

  package main

import (
    "context"
    "fmt"
    "io/ioutil"
    "log"
    "time"

    cdp "github.com/knq/chromedp"
    cdptypes "github.com/knq/chromedp/cdp"
)

func main() {
    var err error

    // create context
    ctxt, cancel := context.WithCancel(context.Background())
    defer cancel()

    // create chrome instance
    c, err := cdp.New(ctxt, cdp.WithLog(log.Printf))
    if err != nil {
        log.Fatal(err)
    }

    // run task list
    var site, res string
    err = c.Run(ctxt, googleSearch("site:brank.as", "Easy Money Management", &site, &res))
    if err != nil {
        log.Fatal(err)
    }

    // shutdown chrome
    err = c.Shutdown(ctxt)
    if err != nil {
        log.Fatal(err)
    }

    // wait for chrome to finish
    err = c.Wait()
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("saved screenshot of #testimonials from search result listing `%s` (%s)", res, site)
}

func googleSearch(q, text string, site, res *string) cdp.Tasks {
    var buf []byte
    sel := fmt.Sprintf(`//a[text()[contains(., '%s')]]`, text)
    return cdp.Tasks{
        cdp.Navigate(`https://www.google.com`),
        cdp.Sleep(2 * time.Second),
        cdp.WaitVisible(`#hplogo`, cdp.ByID),
        cdp.SendKeys(`#lst-ib`, q+"
", cdp.ByID),
        cdp.WaitVisible(`#res`, cdp.ByID),
        cdp.Text(sel, res),
        cdp.Click(sel),
        cdp.Sleep(2 * time.Second),
        cdp.WaitVisible(`#footer`, cdp.ByQuery),
        cdp.WaitNotVisible(`div.v-middle > div.la-ball-clip-rotate`, cdp.ByQuery),
        cdp.Location(site),
        cdp.Screenshot(`#testimonials`, &buf, cdp.ByID),
        cdp.ActionFunc(func(context.Context, cdptypes.Handler) error {
            return ioutil.WriteFile("testimonials.png", buf, 0644)
        }),
    }
}

Here is my answer. The web page is www.google.co.in. The element used is lst-ib, Text box present on the page.

  1. Navigate the page.

  2. Wait until the element is visible.

  3. Read the value of the element. This is first time page is being loaded so obviously value will be "".

  4. Assume, you have modified the value of the element by typing in the text box. Now, if we try to read the value of the same element lst-ib then we should get the updated value.

My code is below,

package main

import (
    "context"
    "log"

    cdp "github.com/knq/chromedp"
)

func main() {
    var err error

    // create context
    ctxt, cancel := context.WithCancel(context.Background())
    defer cancel()

    // create chrome instance
    c, err := cdp.New(ctxt)
    if err != nil {
        log.Fatal(err)
    }

    // run task list
    var res, value, newValue string
    err = c.Run(ctxt, text(&res, &value, &newValue))
    if err != nil {
        log.Fatal(err)
    }

    // shutdown chrome
    err = c.Shutdown(ctxt)
    if err != nil {
        log.Fatal(err)
    }

    // wait for chrome to finish
    err = c.Wait()
    if err != nil {
        log.Fatal(err)
    }

    if len(value) > 1 {
        log.Println("Search Input is present.")
    } else {
        log.Println("Search Input is NOT present.")
    }

    log.Println("New updated value: ", newValue);   

}

func text(res, value, newValue *string) cdp.Tasks {
    return cdp.Tasks{
        cdp.Navigate(`https://www.google.co.in`),
        cdp.WaitVisible(`lst-ib`, cdp.ByID),
        cdp.EvaluateAsDevTools("document.getElementById('lst-ib').value", value),
        cdp.EvaluateAsDevTools("document.getElementById('lst-ib').value='Hello';document.getElementById('lst-ib').value", newValue),
    }
}

To run code use go run <FileName>.go

I am getting following output which was expected:

$ go run main.go 
2017/09/28 20:05:20 Search Input is NOT present.
2017/09/28 20:05:20 New updated value:  Hello

NOTE:

First I checked with Google Chrome Developer Tools to get exact Javascripts for my need. It helps a lot. I have added the screenshot of the Javascript I tried on Chrome Developer Tools.

Screen shot of the Chrome Developer Tool

I hope it helps you. :)

I'm facing the same problem, not sure if it is the same case, here's my code:

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

var existingNodes []*cdp.Node
var nonExistingNodes []*cdp.Node
err := chromedp.Run(ctx,
    chromedp.Navigate(`https://www.google.com`),
    chromedp.WaitVisible("div.ctr-p"),
    chromedp.Query("#fsl a", chromedp.AtLeast(0), chromedp.After(func(i context.Context, n ...*cdp.Node) error {
        existingNodes = n
        return nil
    })),
    chromedp.Query("#fsl div.nonexists", chromedp.AtLeast(0), chromedp.After(func(i context.Context, n ...*cdp.Node) error {
        nonExistingNodes = n
        return nil
    })),
)
if err != nil {
    panic(err)
}
fmt.Printf("existingNodes count: %d
", len(existingNodes))
fmt.Printf("nonExistingNodes count: %d
", len(nonExistingNodes))

the result is: existingNodes count: 3 nonExistingNodes count: 0