I'm trying to write a Python script using selenium's webdriver, to automate the task of uploading invoices to the federal online ledger.
I know this is a common question, but after reading many questions in SO and trying their answers, I couldn't find a solution.
This is the html code I want to select and click on:
<input id="idcontribuyente" type="hidden" name="idContribuyente">
<input class="btn_empresa ui-button ui-widget ui-state-default ui-corner-all" type="button" style= "width:100%" onclick="document.getElementById('idcontribuyente').value='0';document.seleccionaEmpresaForm.submit();" role="button">
These are the main things I've tried so far:
(first with the WebDriverWait() and then with time.sleep(20), just in case there was an error there)
#1
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, "btn_empresa")))
empresa_btn = driver.find_element_by_class_name('btn_empresa')
empresa_btn.click()
#2
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all')))
empresa_btn = driver.find_element_by_css_selector('.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all')
empresa_btn.click()
#3
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, "//input[#type='button']")))
empresa_btn = driver.find_element_by_css_selector("//input[#type='button']")
empresa_btn.click()
#4
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, "//input[#type='button']")))
empresa_btn = driver.find_element_by_xpath("//input[#type='button']")
empresa_btn.click()
#5
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//td[#align="center"]/input')))
empresa_btn = driver.find_element_by_css_selector('//td[#align="center"]/input')
empresa_btn.click()
#6
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH,"//input[#class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']")))
empresa_btn = driver.find_element_by_xpath("//input[#class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']")
empresa_btn.click()
The error when using time.sleep(20):
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: element_name
The error when using WebDriverWait():
selenium.common.exceptions.TimeoutException: Message:
Here's the full html code:
I'm pretty new to this. What am I doing wrong?
many thanks in advance!
UPDATE - SOLUTION:
I found a way, I've used a Selenium IDE and exported the code to inspect it. Apparently it had to do with switching windows. This code works (although it may be more verbose than it needs to be):
vars = {}
vars["window_handles"] = driver.window_handles
# This line already worked before. It is for the previous page
driver.find_element_by_xpath("//div[#title='rcel']").click()
# Here it comes the way to select and click on the problematic button
def wait_for_window(timeout = 2):
time.sleep(round(timeout / 1000))
wh_now = driver.window_handles
wh_then = vars["window_handles"]
if len(wh_now) > len(wh_then):
return set(wh_now).difference(set(wh_then)).pop()
vars["win806"] = wait_for_window(2000)
driver.switch_to.window(vars["win806"])
driver.find_element(By.CSS_SELECTOR, ".btn_empresa").click()
This is how the actual webpage looked like:
red triangle indicates the button I wanted to click on
Maybe try...
driver.find_element_by_xpath("//input[#id='idcontribuyente']/following-sibling::input")
Since it is 2 input tags next to each other, this finds the one by ID first and takes the input sibling directly after it. Not sure it will work since I can't access the URL, but give it a shot
First wait, then click:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all')))
empresa_btn = driver.find_element_by_css_selector('.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all').click()
Some of the steps you've tried were very close.
If the element you want to click is hidden, try using driver.execute_script:
element = driver.find_element_by_css_selector("#idcontribuyente")
driver.execute_script("$(arguments[0]).click();", element)
Update 1, try to click the second input:
element = driver.find_element_by_css_selector(".btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all")
driver.execute_script("$(arguments[0]).click();", element)
Update 2, probably you have few similar css locators similar to above:
try using:
tr:nth-of-type(4)>td>.btn_empresa.ui-button.ui-widget.ui-state-default.ui-corner-all
Update 3
Check if your button is located inside shadow DOM. If it is - none of the methods you tried will work. Check how to enable showing shadow DOM.
Update 4
As mentioned in the comment to your question, your second xpath was good.
Try using it this way:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']")))
empresa_btn = driver.find_element_by_xpath("//input[#class='btn_empresa ui-button ui-widget ui-state-default ui-corner-all']").click()
Related
Here is the HTML I am detecting:
<div class="arrowPopup arrowPopup-start">
<div class="arrowPopupText arrowPopupTextTwoLine arrowPopupText-flashOn" style="white-space: nowrap;">type<br>this</div>
</div>
Here is my code
element = WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, 'arrowPopup
arrowPopup-start')))
This does not work and times out after 20 seconds.
Any help?
Sure it does. This is straight out of the docs,
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "myDynamicElement"))
My guess is that your locator is incorrect or the element is in an IFRAME but we don't have enough info to determine for sure.
wait = new WebDriverWait(driver, 20) # may need to adjust this based on how much time it takes to get a full game
wait.until(EC.element_to_be_clickable((By.XPATH, "//a[text()='Enter a Typing Race']"))).click();
textToType = wait.until(EC.visibility_of_element_located((By.XPATH, "//div[./span[#unselectable]]"))).text;
typeHere = wait.until(EC.visibility_of_element_located((By.XPATH, "//input[contains(#class,'txtInput')][not(#disabled)]")));
for character in textToType
typeHere.send_keys(character);
Thread.Sleep(50); # adjust this to change the typing speed
Since you asked for a breakdown of this XPath
//input[contains(#class,'txtInput')][not(#disabled)]
^ starting at the top of the DOM, find any INPUT
^ whose class contains the text 'txtInput'
^ but does NOT contain the attribute 'disabled'
I am trying to figure out how to get Selenium to click the following section of an Instagram account, here is the html for it.
<a class=" _81NM2" href="/peacocktv/following/" tabindex="0"><span class="g47SY lOXF2">219</span> following</a>
When using instagram, the direct /username/following link does not actually bring up the following list, you would have to click the field manually on the website for it to appear.
log_in = WebDriverWait(driver, 8).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[type = 'submit']"))).click()
not_now = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//button[contains(text(), "Not Now")]')))
not_now.click()
'''not_now2 = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//button[contains(text(), "Not Now")]')))
not_now2.click()'''
search_select = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//input[#placeholder = 'Search']")))
search_select.clear()
'''search_select.send_keys("russwest44", Keys.ENTER)
search_select.send_keys(Keys.ENTER)'''
# Clicks who the person is following:
following = driver.find_elements_by_xpath("//button[contains(text(),'following')]")
following.click()
Which is the best way to come up with the solution
Seems like couple of issues with your current code:
# Clicks who the person is following:
following = driver.find_elements_by_xpath("//button[contains(text(),'following')]")
following.click()
if you pay attention, you've shared HTML with a tag, so your xpath should be
//a[contains(text(),'following')]
not
//button[contains(text(),'following')]
also, you are using find_elements_by_xpath it would return a list of web elements. you can not directly trigger .click on it.
either switch to find_element or
following[0].click()
Sorry guys, I asked the same question before but I can't apply in my real task. (please see previous quest tion here)
I got 2 trouble:
1/ project based on SeleniumLibrary and I don't know how to call find_element_by_xpath or something else in common (import webdriver)
2/ with these code below, the SeleniumLibrary tell me that is not valid XPATH expression.
driver = SeleniumLibrary
driver.open_browser("abc.com")
driver.find_element("//div[#id='react-select-2--value']").click()
driver.find_element("//[test()='Core']) --> Error here "str... is invalid XPATH Expression"
3/ in previous question, I solved the problem (as people's answers)
1.
driver.get("https://react-select.com/home")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.basic-single > div.select__control > div.select__value-container"))).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[contains(#class, 'select__menu')]/div[contains(#class, 'select__menu-list')]//div[contains(#class, 'select__option') and text()='Green']"))).click()
or:
driver.get("https://react-select.com/home")
driver.maximize_window()
driver.find_element_by_xpath("//div[#class='select__value-container select__value-container--has-value css-1hwfws3']").click()
driver.find_element_by_xpath("//*[text()='Green']").click()
# add span tag
<span class="Select-value-label resourceValue" style="margin-left: 5px;" xpath="1">Core</span>
driver.find_element("//[test()='Core'])
you have not provided the tag
driver.find_element("//*[test()='Core']")
you can privide * indicating any tag or specify which tag input,div etc
Also see the elements are in iframe or not , if its inside iframe then you have to switch to it before you could interact with it.
iframe = driver.find_element_by_xpath("//iframe")
driver.switch_to_frame(iframe)
driver.find_element("//div[#id='react-select-2--value']").click()
driver.find_element("//*[test()='Core']")
Abd if you have to interact with element outside iframe then, then you have to switch out from iframe first:
driver.switch_to_default_content()
//rest of code
I'm trying to click on an element (radio button) using Selenium (in Python), I can't disclose the URL because it's a private corporate intranet, but will share the relevants part of code.
So basically this element is within an iframe, thus, I've used the following code to get the element:
# Select the item on main DOM that will udpate the iframe contents
wait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='sm20']"))).click()
# Don't sleep, but only WedDriverWait...
wait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[#name='ifrInterior']")))
# Select the element inside the iframe and click
wait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='gestionesPropias_Equipo']"))).click()
The HTML code for the element is this:
<span class="W1">
<input type="radio" name="gestionesPropias_Equipo" value="1" onclick="javascript:indicadorPropiasEquipo(); ocultarPaginacion('1'); limpiarDatosCapaResultado();">
</span>
I'm interested in clicking this because when we click on it a drop-down is enabled:
If clicked then the dropdown is enabled:
The intersting HTML code for this is
<span id="filtroAsignado" class="W30">
<select name="nuumaAsignado" class="W84">
<option value="">[Todo mi equipo]</option></select>
</span>
Debugging a bit Selenium I can see that the elemtn is found:
And this is actually the base64 image of the element, which is the expected radio button
So I'm wondering why the element actually does not get clicked??
UPDATE: Based on request from #DebanjanB, I'm adding the HTML code from the iframe, which is enclosed inside a div in the main page:
<div id="contenido">
<iframe frameborder="0" id="ifrInterior" name="ifrInterior" src="Seguimiento.do?metodo=inicio" scrolling="auto" frameborder="0"></iframe>
</div>
Actually if I look for the word "iframe", there's only one...
Now checking the iframe source itself, has several iframes hidden but the element I need to interact with is in the iframe mentioned above, the only thing that I forgot to mention is that it's inside a form, but I guess that's not relevant? You can see the whole structure in the following image:
Great question. If you know that selenium found the element, you can use Javascript to click the element directly.
The syntax is:
driver.execute_script("arguments[0].click();", element)
You can also do this, which works the same way:
automate.execute_script("arguments[0].click();", wait.until(EC.element_to_be_clickable((By.XPATH, 'Your xpath here'))))
Essentially you are having Selenium run a javascript click on the element you have found which bypasses Selenium. Let me know if this helps!
I don't see any such issue with your code block either. Perhaps you can try out either of the following options:
Using ActionChains:
ActionChains(driver).move_to_element(WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='gestionesPropias_Equipo' and #type='radio']")))).click().perform()
Using executeScript() method:
driver.execute_script("arguments[0].click();", WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[#name='gestionesPropias_Equipo' and #type='radio']"))))
I am trying to login to beeradvocate.com to scrape (crawl) some beer data.
I tried with selenium but have been brutally failing.
here is the html
<input type="text" name="login" value="" id="ctrl_pageLogin_login" class="textCtrl" tabindex="1" autofocus="autofocus" style="background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEAAAAASUVORK5CYII="); cursor: auto;">
i tried using name and value and class but everything has failed.
I attempted Xpath as my final try, but have failed as well.
website and inspection
My code:
driver=webdriver.Chrome("~~~~\\chromedriver.exe")
driver.get("https://www.beeradvocate.com/community/login/")
from selenium.common.exceptions import TimeoutException
driver.maximize_window()
while True:
try:
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.XPATH,'//*[#id="ctrl_pageLogin_login"]'))).send_keys("scentmaster")
break
except TimeoutException:
print("too much time")
I've made the button work with:
button = driver.find_element_by_xpath('//*[#id="pageLogin"]/dl[3]/dd/input')
driver.execute_script("arguments[0].click();", button)
However, I need to be able to perform sent_keys to type in id and pw to log in...
Anybody got some idea?
There are 2 fields on the page if you use xpath //*[#id = "ctrl_pageLogin_login"], the input field you are referring to is the second. Sadly, the selenium find element by default refers to the first. It will work if you make it like this: (//*[#id = "ctrl_pageLogin_login"])[2].
But I have another suggestion, try to locate element by css selector with this value : form#pageLogin input#ctrl_pageLogin_login
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'form#pageLogin input#ctrl_pageLogin_login'))).send_keys("scentmaster")
#for password
driver.find_element_by_css_selector('form#pageLogin input#ctrl_pageLogin_password').send_keys('your_password')
#for submit
driver.find_element_by_css_selector('form#pageLogin input[type=submit]').click()
To feed the username, try this xpath:
'//form/dl/dd/input[#id="ctrl_pageLogin_login"]'
for the password:
'//form/dl/dd/input[#id="ctrl_pageLogin_password"]'
WebDriverWait(driver, 30).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'form#pageLogin input#ctrl_pageLogin_login'))).send_keys("scentmaster")
#for password
driver.find_element_by_css_selector('form#pageLogin input#ctrl_pageLogin_password').send_keys('your_password')
#for submit
driver.find_element_by_css_selector('form#pageLogin input[type=submit]').click()
The solution above given by frianH worked! :)