I just started working with Selenium webdriver to try automate clicking a button in a discord chat based on preconditions. The problem I am having is being able to classify this button.
For starters, the HTML code is as follows:
<div tabindex="0" class="reactionInner-15NvIl" aria-label="♥️, press to react" aria-pressed="false" role="button"><img src="/assets/1afd3c799f3e158662a70498e83e2a87.svg" alt="♥️" draggable="false" class="emoji"><div class="reactionCount-2mvXRV" style="min-width: 9px;">1</div></div>
What I first tried to do was to find_element_by_xpath:
driver.find_element_by_xpath('/html/body/div/div[1]/div/div[2]/div/div/div/div[2]/div[2]/div[2]/div[1]/div[1]/div/div/div[48]/div[1]/div[2]/div[2]/div[1]/div/div').click()
But, when a new opportunity for this reaction comes up, the xpath changes:
/html/body/div/div[1]/div/div[2]/div/div/div/div[2]/div[2]/div[2]/div[1]/div[1]/div/div/div[50]/div[1]/div[2]/div[2]/div[1]/div/div
Notice the only part changing it the div[48] to div[50]
The next thing I tried was to find_element_by_class_name:
element = driver.find_element_by_class_name('reactionInner-15NvIl')
driver.execute_script("arguments[0].click();", element)
The reason I did this was because I was having a problem with simply doing:
driver.find_element_by_class_name('reactionInner-15NvIl').click()
That code would give me an error saying Message: element click intercepted: Element <div tabindex="0" class="reactionInner-15NvIl" aria-label="💗, press to react" aria-pressed="false" role="button">...</div> is not clickable at point (405, 94). Other element would receive the click: <span id="NewMessagesBarJumpToNewMessages_122" class="span-3ncFWM">...</span> and the code wouldn't run. The program runs with the execute_script but it just isn't doing anything, the button is not being clicked. So if anyone has any idea how to be able to click this button, any help would be appreciated!
You can use xpath in a better way than navigate between the divs, like you did the first time.
First of all, if you can change the HTML to use id, or name, thats better.
In this case, you could use this xpath:
//div[#class = "reactionInner-15NvIl"]
When searching by class, this could return multiple results, so use the function find_elements_by_xpath, and then choose the exactly one
Induce WebDriverWait and wait for element_to_be_clickable() and following css selector.
WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div[class*='reactionInner-'][role='button']"))).click()
You need to import following libraries.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
Update:
Induce Javascript Executor to click.
driver.execute_script("arguments[0].click();", WebDriverWait(driver,20).until(EC.element_to_be_clickable((By.CSS_SELECTOR,"div[class*='reactionInner-'][role='button']"))))
Related
I am working in python with Selenium. When I click on the line
<div tabindex="0" class="page click-enterkey" style="text-align: center; margin: 0px 1em; float: left;">7</div>
and copy the path with a click() or then send.keys(8) it will not go to page 8 it just flashes and keeps on moving to next line of code. But, as a human, if I click the box it changes the elements to show that second picture with an input section.
I have no clue what to do
magicBox = driver.find_element('xpath','//*[#id="searchResults"]/div[1]/div/div[1]/div[2]/div[2]').click()
magicBox.send_keys('7')
magicBox.send_keys(Keys.RETURN)
I also tried
magicBox = driver.find_element('xpath','//*[#id="searchResults"]/div[1]/div/div[1]/div[2]/div[2]').click().send_keys('7')
magicBox.send_keys(Keys.RETURN)
Image
It seems like you are encountering an issue with the send_keys() method not working as expected after you have clicked the element with the click() method.
Here's what you can try to resolve the issue:
First, make sure that you have imported the Keys module:
from selenium.webdriver.common.keys import Keys
After clicking the element, wait for the page to load before using send_keys(). You can use the WebDriverWait class and the expected_conditions module to wait for the element to be clickable before proceeding to the next step.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
magicBox = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[#id="searchResults"]/div[1]/div/div[1]/div[2]/div[2]'))).click()
magicBox.send_keys('7')
magicBox.send_keys(Keys.RETURN)
This should resolve the issue and allow you to successfully send the keys to the element.
Given the HTML you provided, you are trying to send_keys() to a DIV which is not valid. My guess is that if you click the box that contains the "7" in your screenshot, an INPUT HTML element will appear in the DOM that you can send_keys() a new value to.
You might also check the URL and see if ?page=7 or something similar is there and you can just edit the URL to take you directly to the page you want.
I am working on a script for selenium to open a webpage, and click a series of buttons. The first button is an Expander button, shown in the below image
The HTML code from inspecting the button is below, but the button itself is "class="dojoxExpandoIcon dojoxExpandoIconLeft qa-button-toc"
<div class="dojoExpandoPaneInner">
<div data-dojo-attach-point="titleWrapper" class="dojoxExpandoTitle">
<div class="dojoxExpandoContainer">
<div class="dojoxExpandoIcon dojoxExpandoIconLeft qa-button-toc" data-dojo-attach-point="iconNode" data-dojo-attach-event="ondijitclick:_onIconNodeClick" tabindex="0" aria-controls="slideout"><span class="a11yNode">X</span></div>
</div>
The xpath as well, is as follows:
/html[#class='dj_webkit dj_chrome dj_contentbox has-webkit has-no-quirks svg']/body[#class='claro original']/div[#id='border']/div[#id='slideout']/div[#class='dojoExpandoPaneInner']/div[#class='dojoxExpandoTitle']/div[#class='dojoxExpandoContainer']/div[#class='dojoxExpandoIcon dojoxExpandoIconLeft qa-button-toc']
To find this button, I tried the following code one at a time.
driver.find_element_by_css_selector("div[class^='dojoxExpandoIcon']") # find expander by class name
# driver.find_element_by_css_selector("div[class^='dojoxExpandoIcon dojoxExpandoIconLeft qa-button-toc']") # find expander by class name
# driver.find_element_by_css_selector("div.dojoxExpandoContainer")
However, none of them have worked at all, and result in errors such as
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"div.dojoxExpandoIcon.dojoxExpandoIconLeft.qa-button-toc"}
Is there anything I'm doing wrong here?
Try waiting until the locator is clickable:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 15)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".dojoxExpandoIcon.dojoxExpandoIconLeft.qa-button-toc")))
button = driver.find_element_by_css_selector(".dojoxExpandoIcon.dojoxExpandoIconLeft.qa-button-toc").click()
If the number of classes is not stable, remove the ones that are changing and leave only stable ones, for example:
.dojoxExpandoIconLeft.qa-button-toc
Here I just removed one of classes.
Read more about waits here https://selenium-python.readthedocs.io/waits.html.
I'm trying to automate a website using python selenium.
# ----- click on the sign up popup
popup = driver.find_element_by_xpath("/html/body/div[1]/div[4]/section[1]/div/div/div[2]/div/p/a")
popup.click()
click is working fine and the pop-up message is showing perfectly. but after that my I get this error:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element ... is not clickable at point (1263, 589). Other element would receive the click: <div class="mailmunch-inner-overlay" id="mailmunch-inner-overlay-178218df563cebd"></div>
(Session info: chrome=89.0.4389.82)
and the code stop working. what can I do?
please help!
You need to get rid of the overlay. Without the HTML I can only offer a couple of solutions:
Find the dismiss button of the overlay, click it.
Use Javascript to remove the overlay from the DOM
Wait until the overlay disappears
Could it be that you are receiving a described error after you are trying to find an element from that pop-up window? So it's not the line you are thinking that is producing the error. If that is the case, then when you are trying to for example click something in that pop-up window, try the following:
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,""))).click()
You need to import:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
popup = driver.find_element_by_xpath("/html/body/div[1]/div[4]/section[1]/div/div/div[2]/div/p/a")
driver.execute_script("arguments[0].click();", popup)
Try invoking click directly to the element so that it bypasses the overlay or click it's close button.
I have a button, i can successfully find it and capture it's text. However click is not working. Can someone help.
<button class="yellow labeled icon button no-margin" type="button">
<div class="icon my_class"></div>
<span class="ttt">Add new student</span>
</button>
This works:
return driver.find_element(By.XPATH, 'xpath').text
But this does not work and "no exception". Code pass but click not done.
driver.find_element(By.XPATH, 'xpath').click()
You can try clicking it with javascript :
element = driver.find_element(By.XPATH, 'xpath')
driver.execute_script("arguments[0].click();", element)
Of-coarse invoking .text and click() relates to two different states of a WebElement.
Your code block return driver.find_element(By.XPATH, 'xpath').text succeeds as the text Add new student gets rendered within the HTML DOM when you lookout for it. This doesn't guarantees that the WebElement is also interactable by that time. There is a possibility of a JavaScript/Ajax at work rendering the button at that point of time.
It is worth to mention that rendering of the text Add new student resembles to the expected_conditions clause of text_to_be_present_in_element where as interactability (i.e. clickability) resembles to the expected_conditions clause of element_to_be_clickable
Solution
As you mentioned it's an AngularJS based site/element and the click is not getting executed you have to induce WebDriverWait in-conjunction with expected_conditions clause set as element_to_be_clickable as follows :
WebDriverWait(self.driver, 30).until(EC.element_to_be_clickable((By.XPATH, "xpath"))).click()
I'm very new to Selenium.
I'm crawling data from this page. I need to scroll down the page and click on "Load More Arguments" to get more text. This is the location to click on.
<a class="debate-more-btn" href="javascript:void(0);" onclick="loadMoreArguments('15F7E61D-89B8-443A-A21C-13FD5EAA6087');">
Load More Arguments
</a>
I have tried this code but it does not work. Should I need more code to locate to that (I think the 1 has already tell the location to click). Do you have any recommendation? Thank you in advance.
[1] btn_moreDebate = driver.find_elements_by_class_name("debate-more-btn")
[2] btn.click()
Find the link by link text, move to the element and click:
from selenium.webdriver.common.action_chains import ActionChains
link = driver.find_element_by_link_text('Load More Arguments')
ActionChains(browser).move_to_element(link).perform()
link.click()
If you get an exception while finding an element, you may need to use an Explicit Wait:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
link = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, "Load More Arguments")))
ActionChains(browser).move_to_element(link).perform()
link.click()
If I understand your code correctly, I can see a few things wrong.
1. You're using find_elements_by_class_name. I'd recommend using find_element_by_class_name instead. elements returns a list, which isn't needed in a case where there is only one element.
2. You're using btn_moreDebate as the holder for the results of your find_elements, but then interacting with btn.
You should be able to perform the find and click in one action:
driver.find_element_by_class_name("debate-more-btn").click()