5

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+"\n", 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)
        }),
    }
}
Grokify
  • 15,092
  • 6
  • 60
  • 81
Amr Zenga
  • 61
  • 1
  • 8

1 Answers1

3

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. :)

yogesh_desai
  • 449
  • 9
  • 21
  • here is an example of what i need to do : i used to do this with python and selenium : `user = browser.find_element_by_css_selector(user_input)` it gives me a pointer to the element or a nil value which i can check to see if the element was present or not how can i do this same example with chromedp – Amr Zenga Sep 28 '17 at 23:25
  • @AmrZenga : I believe [GoDoc](https://godoc.org/github.com/knq/chromedp#ByID) of the `chromedp` package. There are different functions available. I believe, `BySearch()` will help you in your case. Also, the way with JavaScript, I have mentioned in my answer will also work. :) – yogesh_desai Sep 29 '17 at 17:53
  • @AmrZenga: `Kenneth Shaw` has closed the issue [#120](https://github.com/knq/chromedp/issues/120#event-1270843274) which you have created on GitHub so my answer is correct and works well. So, I would suggest using it if you couldn't figure out a way with other functions of `chromedp` – yogesh_desai Sep 29 '17 at 17:57
  • thx for your time , but all i need a working example of what i mentioned above ,the javascript way didn't work , if you knew what i need plz respond with an example, i only want to know if an item is present at the page or not – Amr Zenga Sep 29 '17 at 21:50
  • @AmrZenga I believe I have already answered your query by giving the example. You can use it by modifying it. Can you show what you have tried with JavaScript which you are saying, it didn't work? So that we can also understand your exact problem. This time show us your actual problem to get better and exact solution. – yogesh_desai Oct 01 '17 at 16:12
  • i tried you solution and it did exactly what the waitvisible do, it waits too much to check,i need an example like the one i mentions with python and selenium , a working example – Amr Zenga Oct 02 '17 at 01:14
  • @AmrZenga: Still you didn't answer my question. You are not showing us your trials and giving us your actual problem. And want us to help you to solve it exactly. You can accept this answer if it worked. Now, modifying it as you wanted is depend on you, so we can't guarantee that. – yogesh_desai Oct 05 '17 at 10:11
  • If the problem to you is that it waits too much to perform the check, skip WaitVisible and do the checking directly. But you should still use WaitVisible in another element to be sure that the page has finished loading. This answer is acceptable. – Lucio Mollinedo Jan 30 '20 at 12:43