AttributeError: 'list' object has no attribute 'click' using Selenium and Python
Solution 1
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
Solution 2
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()
Solution 3
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
Solution 4
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()
Related videos on Youtube
Felix
Keep working on a problem till you get frustrated. Then stop. And repeat process till you make progress
Updated on June 19, 2022Comments
-
Felix almost 2 years
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
data-ptype="Annual"
so I tryed to copy the xpath to click the button (also tried other options but none did work).However, I get the
AttributeError: 'list' object has no attribute 'click'
. I read a lot of similar posts, but wasn't able to fix my problem.. so I assume that javascript event must be called/clicked/performed somehow differnt.. idk Im stuckfrom selenium import webdriver link = 'https://www.investing.com/equities/apple-computer-inc-balance-sheet' driver = webdriver.Firefox() driver.get(link) elm = driver.find_elements_by_xpath("/html/body/div[5]/section/div[8]/div[1]/a[1]").click()
The html is the following:
<a class="newBtn toggleButton LightGray" href="javascript:void(0);" data-type="rf-type-button" data-ptype="Annual" data-pid="6408" data-rtype="BAL">..</a>
-
Felix almost 6 yearsA thanks, but I still get an error cause a popup shows up.. Is there a way around it? Cause I get: ElementClickInterceptedException: 'Element <a class="newBtn toggleButton LightGray" href="javascript:void(0);"> is not clickable at point (175.29999542236328,530.3166961669922) because another element <div class="consentBarWrapper"> obscures it'
-
Druta Ruslan almost 6 yearsi update my answer, try to add
options
to openfirefox
on full window, but i run the code withoutoptions
and it works -
cruisepandey almost 6 years@Felix : I have updated my answer under update section. This code works fine on my machine. You will have to scroll down to interact with Annual button. Thanks !
-
JayB almost 4 yearsWorked like a charm.Thanks!
-
sonali over 3 yearsthis is a comment, not an answer