1

Here is the HTML of the button I am trying to locate, it appears to me as an angular component:

<tab-button class="tab-button _ngcontent-jne-2 _nghost-jne-3" focusitem="" role="tab" aria-selected="false" tabindex="-1" aria-disabled="false" aria-label="Offline Reporting">
    <!---->
    <div class="content displayed-value _ngcontent-jne-3">Offline Reporting</div>
    <!---->
    <material-ripple class="_ngcontent-jne-3">
        <div class="__acx-ripple" style="top: -103px; left: -45px; transform: translate(17px, -1px) scale(0.88156);"></div>
        <div class="__acx-ripple" style="top: -101px; left: -62px; transform: translate(34px, -3px) scale(0.88156);"></div>
    </material-ripple>
</tab-button>

Note that I want to locate tab-button which has aria-label = Offline Reporting. Here's what all I have tried:

element = driver.find_element_by_xpath("//tab-button[@aria-label='Offline Reporting']")

element = driver.find_element_by_tag("tab-button")

element = driver.find_element_by_tag_name("tab-button")

element = driver.find_element_by_css_selector("tab-button")

None of the above actually worked. Can you point out the right way to do the same? I have to locate the tab-button (Out of many) which has aria-label as Offline Reporting

Quick Edit

Note that I am using Selenium Web Driver for the same purpose and the page I am trying to load is an Angular page. From my understanding, the content is dynamically rendered here and so even though I can see it in element inspector, It's not getting located with find_element function.

Here is the snapshot of the same: enter image description here

Note that I have tried everything that's mentioned in the current answers... that is waiting for the page to load completely and even if it loads completely I tried a delay of 50s as shown below:

WebDriverWait(driver, 50).until(EC.visibility_of_element_located((By.XPATH, "//tab-button[contains(@class, 'tab-button') and @aria-label='Offline Reporting']")))

But this ended up in timeout as well. The point I am trying to raise through these lines is that this is a dynamically rendered page and so to handle it there's some other middleware mechanicsm needed like scrapy-selenium

Shivam Sahil
  • 4,055
  • 3
  • 31
  • 62

2 Answers2

1

Try to wait for button to be become visible and clickable:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//tab-button[@aria-label='Offline Reporting']")))
button.click()
DonnyFlaw
  • 581
  • 3
  • 9
  • Tried it as you said... no luck, it still can't find this element. – Shivam Sahil Nov 24 '20 at 09:20
  • @ShivamSahil is it located inside an iframe? – DonnyFlaw Nov 24 '20 at 09:26
  • Actually it's an Angular site and I was going through many docs when I realized scrapping dynamic sites is somewhat tricky. To your question it's not located inside iframe rather its located inside – Shivam Sahil Nov 24 '20 at 09:28
  • @ShivamSahil how about `"//*[name()='tab-button' and @aria-label='Offline Reporting']"`? – DonnyFlaw Nov 24 '20 at 09:34
  • This doesn't work as well... Actually these pages first request to an external API and then load up... so basically for some reason it's not able to locate it as they're dynamically loading even when they load up... – Shivam Sahil Nov 24 '20 at 09:46
  • @ShivamSahil can you share the page URL? – DonnyFlaw Nov 24 '20 at 09:56
  • @DonnyFlaw As a valued contributor on StackOverflow it isn't fair to ask for the page URL unless OP mentions the URL voluntarily. However, OP have provided the relevant text based HTML and that can be a good starting point. – undetected Selenium Nov 24 '20 at 10:26
0

To locate the element with text as Offline Reporting you can use either of the following Locator Strategies:

  • Using css_selector:

    element = driver.find_element_by_css_selector("tab-button.tab-button[aria-label='Offline Reporting']")
    
  • Using xpath:

    element = driver.find_element_by_xpath("//tab-button[contains(@class, 'tab-button') and @aria-label='Offline Reporting']")
    

As the element is an Angular element, ideally to locate the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "tab-button.tab-button[aria-label='Offline Reporting']")))
    
  • Using XPATH:

    element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//tab-button[contains(@class, 'tab-button') and @aria-label='Offline Reporting']")))
    
  • Note : You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Hi, Thank you very much for our answer... Though your answer was really helpful but it didn't solve my problem... using what you mentioned also ended up timing out as the page is dynamically rendered via API request and not all of the contents are actual content even though I can inspect them in inspector they're not located via selenium. – Shivam Sahil Nov 24 '20 at 11:25
  • @ShivamSahil Checkout the updated answer and let me know the status – undetected Selenium Nov 24 '20 at 11:32
  • Hi... tried that as well... this didn't work as well. :( Also I have added some edits in question, just go through it for even more clarification – Shivam Sahil Nov 24 '20 at 11:44
  • Traceback (most recent call last): File "", line 1, in element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//tab-button[contains(@class, 'tab-button') and @aria-label='Offline Reporting']"))) File "C:\Users\DELL\AppData\Local\Programs\Python\Python36\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException: Message: – Shivam Sahil Nov 24 '20 at 11:50