1

I am running into this issue when trying to click a button using selenium. The button html reads as below:

<button class="Component-button-0-2-65 Component-button-d1-0-2-68">and 5 more</button>

My code is here:

button = EC.element_to_be_clickable((By.XPATH,'.//button[contains(@class,"Component-button-d")]'))
    if button:
        print("TRUE")
        button.click()

My output is:

TRUE
Traceback (most recent call last):
  File "", line 47, in <module>
    button.click()
AttributeError: 'function' object has no attribute 'click'

I am stumped as to why 'button' element is found by selenium (print(True) statement is executed) but then the click() method returns an attribute error.

This is the page I am scraping data from: https://religiondatabase.org/browse/regions I am able to extract all the information I need on the page, so the code leading up to the click is working.

I was expecting the item to be clickable. I'm not sure how to troubleshoot the attribute error (function object has no attribute click). Because it I paste the xpath into the webpage, it highlights the correct element.

2 Answers 2

1

The element search is always done through the driver object which is the WebDriver instance in it's core form:

driver.find_element(By.XPATH, "element_xpath")

But when you apply WebDriverWait, the wait configurations are applied on the driver object.

WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "element_xpath")))    

So even during WebDriverWait the driver object needs to be present along with the expected_conditions and the locator strategy.


This usecase

This line of code:

button = EC.element_to_be_clickable((By.XPATH,'.//button[contains(@class,"Component-button-d")]'))

button object references to a junk value but on probing returns true and prints TRUE but the click can't be performed as button is not of WebElement type.


Solution

Given the HTML:

<button class="Component-button-0-2-65 Component-button-d1-0-2-68">and 5 more</button>

To click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:

  • Using XPATH with classname:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "//button[contains(@class,'Component-button-d')]"))).click()
    
  • Using XPATH with classname and innerText:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[contains(@class,'Component-button-d') and text()='and 5 more']"))).click()
    
  • 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
    
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for such a detailed response. I really appreciate it. I'll choose this answer as accepted since this provides more detail.
0

Your code is incorrect. You can find below an example of how you can use Expected Conditions (along with WebdriverWait):

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
## [...define your driver here, other imports etc]

wait = WebDriverWait(driver, 25)

##[open a url, etc]
element = wait.until(EC.presence_of_element_located((By.XPATH, '//div[@class="input-group"]')))
element.click()

Selenium documentation can be found here.

1 Comment

Thank you for your answer, I now understand what is wrong.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.