1

I'm trying to get a particular field Further Information out of a table from a webpage using vba selenium bindings. I got success when I tried with python in combination with selenium using textContent instead of text as the latter is scraping nothing. However, the problem is I can't make use of this textContent within vba selenium. This is the link to my earlier post where I've asked this same question tagging different language.

Website link

I've tried with:

Sub ScrapeContent()
    Const URL$ = "https://www.sharedividends.com.au/mlt-dividend-history/"
    Dim driver As New ChromeDriver, elem As Object, R&

    driver.get URL

    For Each elem In driver.FindElementsByXPath("//*[@id='divTable']//tbody//tr[@role='row']", timeout:=10000)
        R = R + 1: Cells(R, 1) = elem.FindElementByXPath("(.//td)[8]").Text
    Next elem
End Sub

The field that I'm interested in:

enter image description here

When I run my above script, It fetches nothing. It doesn't throw any error either. FYI, the xpaths I've defined within the script is accurate.

How can I get that particular field (available in every row) out of the table from that website?

MITHU
  • 113
  • 3
  • 12
  • 41
  • Please don't offer any solution using different `xpaths` or `selectors` as my intention is to know how I can use `textContent` or something similar in future cases. – MITHU Aug 09 '19 at 19:18
  • I don't see why `.Text` won't work... are you sure that you are giving the page enough time to put the data into the cell after expanding that part of the table? – JeffC Aug 09 '19 at 20:24
  • Yes, JeffC. I've given enough time to load that content by increasing the timeout here `timeout:=20000`. – MITHU Aug 09 '19 at 20:27
  • Does that wait for presence or visibility? My guess is that it waits for presence. It also might be that no matter which it waits for it won't be enough because the element might be visible but the text isn't in there yet because it's generated dynamically. – JeffC Aug 09 '19 at 20:31
  • 1
    Have you noticed that if you maximize the page, the entire table is displayed and you don't have to click the expand button? Doing that might solve your problems. FYI... the reason `textContent` works when `.text` doesn't is because Selenium was designed to interact with the page as a user would. The text you are looking for in the table isn't visible... it's in `display:none` tags. `.text` returns visible text (none) where `textContent` is JavaScript which will return text whether it's visible or not. – JeffC Aug 09 '19 at 20:34

4 Answers4

2

I suppose there isn't any elegant way of using textContent in vba selenium bindings. However, you can go with the following approach for now.

Sub ScrapeContent()
    Const URL$ = "https://www.sharedividends.com.au/mlt-dividend-history/"
    Dim driver As New ChromeDriver, elem As Object, oItem As Object, R&

    driver.get URL

    For Each elem In driver.FindElementsByXPath("//*[@id='divTable']//tbody//tr", timeout:=10000)
        Set oItem = elem.FindElementByXPath("(.//td)[8]", Raise:=False)

        If Not oItem Is Nothing Then
            R = R + 1: Cells(R, 1) = driver.ExecuteScript("return arguments[0].textContent;", oItem)
        End If
    Next elem
End Sub
JeffC
  • 22,180
  • 5
  • 32
  • 55
SIM
  • 21,997
  • 5
  • 37
  • 109
1

Apologies didn't see your stipulation (my bad) on textContent and xpath so here is an alternative for future readers. However, looks like @sim has the covered.

Gather a collection of all elements matched by

.sorting_1

Loop that collection and click each one.

Then gather all elements matched by

[data-dt-column='7'] .dtr-data

and extract the .text property.

Something like:

Dim elem As Object, elems As Object

Set elems = driver.FindElementsByCss(".sorting_1")

For Each elem in elems
    elem.click
Next

Set elems = driver.FindElementsByCss("[data-dt-column='7'] .dtr-data")
For Each elem in elems
    Debug.Print elem.text
Next
QHarr
  • 83,427
  • 12
  • 54
  • 101
1

There are a couple of things to observe in this answer to your previous question

Actually, the text Further Information 10.4C FRANKED @ 30%; DRP NIL DISCOUNT is available is 2 seperate place:

  • When the circular button having plus sign is green with the attribute style="display: none;":

display_none

This the place from where your accepted solution reads the text using get_attribute('textContent')


Of coarse there can be a better approach.

  • In this answer you will find the solution clicks on all the circular buttons having plus sign is green so they turns red as follows:

    for elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//table[@aria-describedby='divTable_info']//tbody//tr/td[@class='sorting_1']"))):
        elem.click()
    
  • Snapshot:

red_button

  • The text Further Information 10.4C FRANKED @ 30%; DRP NIL DISCOUNT is read from a <span> tag using get_attribute("innerHTML") as follows:

span


Conclusion

Using the same logic you can use either .Text or .Attribute("innerHTML") through to cater to your needs.

You can find a detailed discussion regarding the usage of .Text or .Attribute("innerHTML") in Trying with Selenium + Excel VBA to scrape code from a site in Chrome Browser

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • You've put nothing but python code and screenshots in a question about VBA. Also, if you'd read the other answers before answering (as you are supposed to), you would have seen that OP has already tried the VBA equivalent of `get_attribute()` and it's not implemented in VBA. – JeffC Aug 09 '19 at 20:36
0

You can try using .getAttribute method.

elem.FindElementByXPath("(.//td)[8]").getAttribute(...)
frianH
  • 7,295
  • 6
  • 20
  • 45
  • Nope, that won't be of any help. I tried with `.getAttribute("textContent")` already. – MITHU Aug 09 '19 at 19:16
  • Yep I did. The script throws error (object doesn't support this property or method) if I use `.getAttribute("innerHTML")` or `.getAttribute("innerText")`. – MITHU Aug 09 '19 at 19:27