0

I was trying to scrape this URL and trying to navigate the next Brand list on the website. I use selenium click by.XPATH and got the error TypeError: 'str' object is not callable,

this is the code I executed

for i in soup.find_all('div', class_='ShopBrandsAlphabetically-brandLink'):
    title = i.find('a', href = True)
    results.append(title.text.strip())
    time.sleep(2)
    driver.find_element(By.XPATH("//button[@name='0-9']")). click()

and this is the webpage element

<button name="0-9" value="0-9" type="button" data-hb-id="Button" class="_1vl5e1z1_713 _1vl5e1z2_713 _1vl5e1z6_713 _1vl5e1z9_713 _1vl5e1z11_713"><span class="_1vl5e1zd_713 _1vl5e1z12_713 _1vl5e1z16_713 _1vl5e1z18_713"><span class="ShopBrandsAlphabetically-filter"><p data-hb-id="Text" class="j3rpje110_713 nhya890_713" style="--j3rpje10w_713:inherit">0-9</p></span></span></button>

can anyone tell me where's my mistake?

Ajeet Verma
  • 2,938
  • 3
  • 13
  • 24
NSilt
  • 1

3 Answers3

1

You're using By.XPATH wrongly.

The call should be this:

driver.find_element(By.XPATH, "//button[@name='0-9']")

But instead you did this:

driver.find_element(By.XPATH("//button[@name='0-9']"))

The parentheses immediately following By.XPATH(...) indicate that you're treating it as a function. But it is not a function.

John Gordon
  • 29,573
  • 7
  • 33
  • 58
0

I believe you have to put a comma between By.XPATH and "//button[@name='0-9']".

Because you are putting By.XPATH("//button[@name='0-9']") inside the type parameter, selenium thinks you are tying to click By.XPATH("//button[@name='0-9']"), which is a string and not the button you are attempting to access.

In conclusion, try using this:

driver.find_element(By.XPATH,"//button[@name='0-9']").click()

This should get the button you are tying to access.

Phantom37
  • 21
  • 8
0

As per the defination find_element() finds an element given a By strategy and a locator and is defined as:

def find_element(self, by=By.ID, value: Optional[str] = None) -> WebElement:
    """Find an element given a By strategy and locator.

    :Usage:
        ::

            element = driver.find_element(By.ID, 'foo')

    :rtype: WebElement
    """

Solution

In your usecase instead of function you need to pass as a tuple as follows:

driver.find_element(By.XPATH, "//button[@name='0-9']").click()

However the desired element is a JavaScript enabled element, so to click on the clickable 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:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[name='0-9'][value='0-9'] p"))).click()
    
  • Using XPATH:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@name='0-9' and @value='0-9']//p[text()='0-9']"))).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
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352