'list' object has no attribute 'click' - python

I'm trying to close a modal with the 'x' button but I'm getting this error 'list' object has no attribute 'click' so I looked for other answers and they said to use close_button[0].click() since find_by_element stores a list but still getting error as IndexError: list index out of range
I need help to close this modal
my code
close_button=browser.find_elements_by_xpath('//*[#id="prefix-overlay-header"]/button')
close_button[0].click()
The element that I'm trying to access and close.

My 2c using Expected Conditions (waits):
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Firefox()
wait = WebDriverWait(driver, 10)
driver.maximize_window()
driver.get('https://site.tld')
el = wait.until(EC.element_to_be_clickable((By.XPATH, '//button[text()="Close subscription dialog"]')))
el.click()
Based on your comment, you may want to use the following code after "click is executed" and which opens a new tab:
wait.until(EC.number_of_windows_to_be(2)) # wait for 2 tabs (windows) to be open
driver.switch_to_window(driver.window_handles[1]) # switch to newly opened tab

It is because your a trying to find the elements by
browser.find_elements_by path
Note that you can see elements. Elements is a list.It is plural
Try this:
browser.find_element_by_path
And then use closebutton.click()

I found the answer. As there is a space you should use css selector. The important things are the points(.)
close_button = browser.find_element_by_css_selector('.prefix-overlay-close.prefix-overlay-action-later')
close_button.click()
It worked for me in your given website. Please check once

Related

How to click on the shadowbox in selenium-python?

I am trying to create an automation program. I want to click on the "Accept Cookies" shadowbox on the given website.
Here's how I have tried to achieve this:
driver = webdriver.Chrome('chromedriver')
driver.get(r'https://www.studydrive.net/')
script = '''return document.querySelector('#usercentrics-root').shadowRoot.querySelector('button[aria-label="Accept All"]')'''
accept_all_btn = driver.execute_script(script)
accept_all_btn.click()
Here's the error that I get after following this approach:
AttributeError: 'NoneType' object has no attribute 'click'
I don't know, what I am doing wrong here. Any help is appreciated. Thank you in advance.
wait=WebDriverWait(driver, 60)
driver.get("https://www.studydrive.net/")
elem = wait.until(EC.presence_of_element_located((By.ID,"usercentrics-root")))
script = '''return document.querySelector('#usercentrics-root').shadowRoot.querySelector('button[data-testid="uc-accept-all-button"]')'''
accept_all_btn = driver.execute_script(script)
accept_all_btn.click()
Simply wait for the element and then proceed to click the accept all button. No aria-label was specified so I used another attribute.
Imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
The element Accept all button is within a #shadow-root (open)
Solution
Tto click() on the desired element you need to use shadowRoot.querySelector()
You can use the following Locator Strategy:
driver = webdriver.Chrome(service=s, options=options)
driver.get("https://www.studydrive.net/")
time.sleep(5)
accept_all = driver.execute_script('''return document.querySelector("#usercentrics-root").shadowRoot.querySelector("button[data-testid='uc-accept-all-button']")''')
accept_all.click()
PS: The cookie popup surfaces on the screen after significant amount of time, so you may have to induce some waits
References
You can find a couple of relevant detailed discussions in:
How to locate the First name field within shadow-root (open) within the website https://www.virustotal.com using Selenium and Python
How to get past a cookie agreement page using Python and Selenium?
Unable to locate the Sign In element within #shadow-root (open) using Selenium and Python

Selecting option from dropdown menu using Selenium; Unable to locate element

I need to select an element from a dropdown list. I'm using Selenium, but I'm having difficulty selecting the dropdown list itself to select from the available options and keep receiving an error "Message: no such element: Unable to locate element:". I've tried the following:
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
driver=webdriver.Chrome()
driver.get('mysite.com')
driver.implicitly_wait(10)
driver.find_element_by_xpath('//*[#id="xpath-example"]').click()
select.select_by_visable_text('option 1')
elem=driver.find_element_by_xpath('//*[#id="xpath-example"]')
sel = Select(elem)
sel.select_by_index(1)
sel.select_by_visible_text("option 1")
You need to find the elem and put it into the Select first of all. Then try one of the two options.
Can you try using by xpath click() action with:
//*[#id="x"]/option[1]
something like:
driver.find_element_by_xpath('//*[#id="x"]/option[1]').click()
A couple of things: first, you may want find_elements which returns a list as opposed to find element which returns an object.
Additionally, Because the element which you are trying to access may become visible at an unknown time, you could employ use of a timed wait, which (by your code) would always wait 10 seconds. Or you could make use of the webdriverwait function which would wait only until it was visible (which could be 2,3 or any time up to a timeout which you define)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver=webdriver.Chrome()
driver.get('mysite.com')
try:
elem = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.XPATH, '//*[#id="xpath-example"]')))
item = elem.select_by_visible_text('option 1')
except:
print("Couldn't find elem")
pass

Clicking multiple links with the same link text using python selenium

I'm trying to get my program (written in python) to open multiple links at the same time. I can open one link – but when I change my command from find_element_by_link_text to find_elements_by_link_text it doesn't work.
For context, I'm trying to open all links on the page with the name 'Annual Report'.
Here's the code I've tried:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import options
driver = webdriver.Chrome()
driver.get('https://webb-site.com/')
search = driver.find_element_by_name('code')
search.click()
search.send_keys("1830")
search.send_keys(Keys.RETURN)
element = driver.find_element_by_link_text('Financials')
element.click()
element = driver.find_elements_by_link_text('Annual Report')
element.click()
Here's my error
AttributeError: 'list' object has no attribute 'click'
As I said above. By removing the s in 'elements' it works fine but only opens the first 'Annual Report'.
You are getting AttributeError: 'list' object has no attribute 'click' error due to click on a list object. If you want to click multiple items then use a for loop.
driver = webdriver.Chrome()
driver.get('https://webb-site.com/')
search = driver.find_element_by_name('code')
search.click()
search.send_keys("1830")
search.send_keys(Keys.RETURN)
element = driver.find_element_by_link_text('Financials')
element.click()
element = driver.find_elements_by_link_text('Annual Report')
# print(element)
# print(len(element))
# element.click()
for c in element:
c.click()
You are calling click to a list object.
The object element in the last line:
element = driver.find_elements_by_link_text('Annual Report')
is a list.
When you call find_elements you get in return a list.
Just change it to:
element = driver.find_element_by_link_text('Annual Report')
Edit
As #Samsul added, to click on all the elements you'll need to loop through the list.

Element Not Clickable - even though it is there

Hoping you can help. I'm relatively new to Python and Selenium. I'm trying to pull together a simple script that will automate news searching on various websites. The primary focus was football and to go and get me the latest Manchester United news from a couple of places and save the list of link titles and URLs for me. I could then look through the links myself and choose anything I wanted to review.
In trying the the independent newspaper (https://www.independent.co.uk/) I seem to have come up against a problem with element not interactable when using the following approaches:
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome('chromedriver')
driver.get('https://www.independent.co.uk')
time.sleep(3)
#accept the cookies/privacy bit
OK = driver.find_element_by_id('qcCmpButtons')
OK.click()
#wait a few seconds, just in case
time.sleep(5)
search_toggle = driver.find_element_by_class_name('icon-search.dropdown-toggle')
search_toggle.click()
This throws the selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable error
I've also tried with XPATH
search_toggle = driver.find_element_by_xpath('//*[#id="quick-search-toggle"]')
and I also tried ID.
I did a lot of reading on here and then also tried using WebDriverWait and execute_script methods:
element = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '//*[#id="quick-search-toggle"]')))
driver.execute_script("arguments[0].click();", element)
This didn't seem to error but the search box never appeared, i.e. the appropriate click didn't happen.
Any help you could give would be fantastic.
Thanks,
Pete
Your locator is //*[#id="quick-search-toggle"], there are 2 on the page. The first is invisible and the second is visible. By default selenium refers to the first element, sadly the element you mean is the second one, so you need another unique locator. Try this:
search_toggle = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//div[#class="row secondary"]//a[#id="quick-search-toggle"]')))
search_toggle.click()
First you need to open search box, then send search keys:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
import os
chrome_options = Options()
chrome_options.add_argument("--start-maximized")
browser = webdriver.Chrome(executable_path=os.path.abspath(os.getcwd()) + "/chromedriver", options=chrome_options)
link = 'https://www.independent.co.uk'
browser.get(link)
# accept privacy
button = browser.find_element_by_xpath('//*[#id="qcCmpButtons"]/button').click()
# open search box
li = browser.find_element_by_xpath('//*[#id="masthead"]/div[3]/nav[2]/ul/li[1]')
search_tab = li.find_element_by_tag_name('a').click()
# send keys to search box
search = browser.find_element_by_xpath('//*[#id="gsc-i-id1"]')
search.send_keys("python")
search.send_keys(Keys.RETURN)
Can you try with below steps
search_toggle = driver.find_element_by_xpath('//*[#class="row secondary"]/nav[2]/ul/li[1]/a')
search_toggle.click()

Selenium Element not visible exception

I have been tasked with writing a parser to click a button on a website and I am having issues to click only one of the buttons. The following code works on every button except one.
Here's the html:
http://pastebin.com/6dLF5ru8
here's the source html:
http://pastebin.com/XhsedGLb
python code:
driver = webdriver.Firefox()
...
el = driver.find_element_by_id("-spel-nba")
actions.move_to_element(el)
actions.sleep(.1)
actions.click()
actions.perform()
I am getting this error.
ElementNotVisibleException: Message: Element is not currently visible and so may not be interacted with
as per Saifur I just tried waits with the same element not visible exception:
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.XPATH, "//input[contains(#id,'spsel')][#value='nba']"))).click()
If you look at the page source, you'll understand that almost all of theSELECT, DIV elements are faked and created from JavaScript, that is why webdriver cannot SEE them.
There's a workaround though, by using ActionChains to open your developer console, and inject an artificial CLICK on the desired element, which in fact, is the Label triggering the NBA data loading... here's a working example:
from selenium import webdriver
from selenium.webdriver.common import action_chains, keys
import time
driver = webdriver.Firefox()
driver.get('Your URL here...')
assert 'NBA' in driver.page_source
action = action_chains.ActionChains(driver)
# open up the developer console, mine on MAC, yours may be diff key combo
action.send_keys(keys.Keys.COMMAND+keys.Keys.ALT+'i')
action.perform()
time.sleep(3)
# this below ENTER is to rid of the above "i"
action.send_keys(keys.Keys.ENTER)
# inject the JavaScript...
action.send_keys("document.querySelectorAll('label.boxed')[1].click()"+keys.Keys.ENTER)
action.perform()
Alternatively to replace all the ActionChains commands, you can simply run execute_script like this:
driver.execute_script("document.querySelectorAll('label.boxed')[1].click()")
There you go, at least on my local file anyway... Hope this helps!
What worked for me was to find the element just before the problematic one (that is, just before it in terms of tab order), then call Tab on that element.
from selenium.webdriver.common.keys import Keys
elem = br.find_element_by_name("username")
elem.send_keys(Keys.TAB) # tab over to not-visible element
After doing that, I was able to send actions to the element.
The actual solution of this thread did not work for me.
however,
this one did :
element = WebDriverWait(driver, 3).until(EC.visibility_of_element_located((By.XPATH, xpaths['your_xpath_path'])))
the trick is to use :
EC.visibility_of_element_located
the WebDriverWait
WebDriverWait
from this import :
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
I suggest you use xpath with explicit wait
//input[contains(#id,'spsel')][#value='nba']
if "Element is not currently visible" then make it VISIBLE
f.e.
>>> before is hidden top is outside of page
<input type="file" style="position: absolute;top:-999999" name="file_u">
>>> after move top on in page area
DRIVER.execute_script("document.getElementByName('file_u').style.top = 0;")
time.sleep(1); # give some time to render
DRIVER.find_element_by_name("file_u").send_keys("/tmp/img.png")
Instead of get_element_by_id() you can try elem = browser.find_element_by_css_selector('#elemId') (go to that webpage and the element, right click it and Copy CSS Selector, or something like that.) This is what i did and it works. You also try find_element_by_link_text(text), find_element_by_partial_link_text(text), find_element_by_tag_name(tagName_case_insensitive_here), find_element_by_name(name) etc. Something will work. After the id the CSS Selector is your best bet.
I ended up using #twasbrillig's solution, but instead of finding the previous element and sending a TAB keypress, I find the desired element, send a TAB keypress with that element, and then a SHIFT + TAB keypress to the driver:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
el = driver.find_element_by_id("-spel-nba")
el.send_keys(Keys.TAB)
webdriver.ActionChains(driver).key_down(Keys.SHIFT).send_keys(Keys.TAB).key_up(Keys.SHIFT)
I tried using the other methods but in the end found that the simplest way was to just try and click the button, and catch the error. This allows me to perform other actions based on if it worked (True) or didn't (False).
def click_button(html_object):
try:
html_object.click()
except:
return False #most likely because it is NotVisible object and can be ignored
return True
...
...
click_button(actions)
The way I solved this in python was:
try:
# the element you want to scroll to
element = driver.find_element_by_id("some_id")
ActionChains(driver).move_to_element(element).perform()
element.send_keys(Keys.TAB).key_up(Keys.SHIFT)
#element.click()
except Exception as e:
print(e)

Categories

Resources