AttributeError: 'list' object has no attribute 'click' using Selenium and Python

前端 未结 4 1120
无人共我
无人共我 2020-12-19 13:12

I\'d like to click the button \'Annual\' at a page that is by default set on \'Quarterly\'. There are two links that are basically called the same, except that one has

相关标签:
4条回答
  • 2020-12-19 13:29

    As per the documentation find_elements_by_xpath(xpath) returns a List with elements if any was found or else an empty list if not. Python's List have no click() method associated with it. Instead find_element_by_xpath(xpath) method have the click() method associated with it. So you have to use find_element_by_xpath(xpath) method inducing a waiter through WebDriverWait inconjunction with expected_conditions set as element_to_be_clickable(locator) as follows:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[@class='newBtn toggleButton LightGray' and @data-type='rf-type-button']"))).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
    
    0 讨论(0)
  • 2020-12-19 13:39

    Notice that find_elements_by_xpath is plural it returns a list of elements. Not just one. The list can contain none, exactly one, or more elements.

    You can for example click the first match with:

    driver.find_elements_by_xpath("/html/body/div[5]/section/div[8]/div[1]/a[1]")[0].click()

    or iterate through the list and click all these elements, or you can use the find_element_by_xpath (which returns a single element, if it can be found):

    driver.find_element_by_xpath("/html/body/div[5]/section/div[8]/div[1]/a[1]").click()
    0 讨论(0)
  • 2020-12-19 13:43

    you need to use find_element_by_xpath not find_elements_by_xpath that return a list

    driver.find_element_by_xpath("/html/body/div[5]/section/div[8]/div[1]/a[1]").click()
    

    Also i think is better to use Waits for example.

    from selenium.webdriver.common.by import By    
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.firefox.options import Options
    
    options = Options()
    options.add_argument("--window-size=1920,1080")
    driver = webdriver.Firefox(firefox_options=options)
    
    path = "/html/body/div[5]/section/div[8]/div[1]/a[1]"
    try:
        element = WebDriverWait(driver, 5).until(
                               EC.element_to_be_clickable((By.XPATH, path)))
        element.click()
    finally:
        driver.quit()
    
    0 讨论(0)
  • 2020-12-19 13:51

    I would still suggest you to go with linkText over XPATH. Reason this xpath : /html/body/div[5]/section/div[8]/div[1]/a[1] is quite absolute and can be failed if there is one more div added or removed from HTML. Whereas chances of changing the link Text is very minimal.

    So, Instead of this code :

    elm = driver.find_elements_by_xpath("/html/body/div[5]/section/div[8]/div[1]/a[1]").click()
    

    try this code :

    annual_link = driver.find_element_by_link_text('Annual')
    annual_link.click()
    

    and yes @Druta is right, use find_element for one web element and find_elements for list of web element. and it is always good to have explicit wait.

    Create instance of explicit wait like this :

    wait = WebDriverWait(driver,20)
    

    and use the wait reference like this :

    wait.until(EC.elementToBeClickable(By.LINK_TEXT, 'Annual'))  
    

    UPDATE:

    from selenium import webdriver
    link = 'https://www.investing.com/equities/apple-computer-inc-balance-sheet'
    
    driver = webdriver.Firefox()
    driver.maximize_window()
    wait = WebDriverWait(driver,40)
    driver.get(link)  
    
    driver.execute_script("window.scrollTo(0, 200)") 
    
    wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Annual')))
    annual_link = driver.find_element_by_link_text('Annual')
    annual_link.click()
    print(annual_link.text)  
    

    make sure to import these :

    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC 
    
    0 讨论(0)
提交回复
热议问题