I'm trying to code nicely against a web site with AJAX like functionality, and using pysaunter (http://element34.ca/products/saunter/pysaunter).
When I use the available synchronization method wait_for_available, perhaps improperly, my code does more or less what I want, but the Selenium server node throws asserts like following while the class is not yet present:
org.openqa.selenium.remote.ErrorHandler$UnknownServerException: Unable to locate element: {"method":"css selector","selector":".ng-scope.ready.idle"}
I'd like to use WebDriverWait, I think like this:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
WebDriverWait(self.driver, 30).until(EC.presence_of_element_located((By.CLASS_NAME,'idle')))
But when I try that, I still get the above exception from a Firefox remote webdriver, and the following from a chrome remote webdriver:
13:09:22.525 WARN - Exception: no such element
(Session info: chrome=29.0.1547.76)
(Driver info: chromedriver=2.0,platform=Mac OS X 10.8.5 x86_64) (WARNING: The server did not provide any stacktrace information)
Is it possible to avoid exceptions from Selenium Server when looking for an element that will likely not be present right away, when running remote webdriver using Python?
Can anyone point me to an example of the proper way to use WebDriverWait from pysaunter? I'm starting from here:
http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp
and
(see also Element 34 blog posting "WebDriverWait and Python" from July 9th, 2012)
TIA
If you look into the WebDriverWait code you will see that you can give the constructor a list of exceptions to ignore. One such list is pre-defined, 'IGNORED_EXCEPTIONS', that is set to [NoSuchElementException]. So you can just add 'ignored_exceptions=IGNORED_EXCEPTIONS' to the WebDriverWait constructor, i.e.:
WebDriverWait(self.driver, 30, ignored_exceptions=IGNORED_EXCEPTIONS).until(...)
Then those exceptions will be ignored and it will continue to try until it succeeds or times out.
Related
I have been trying to send a URL link to a text area. I am using python3 and Chrome Version 109.0.5414.119. It worked fine on my local OSX machine but when I tried to automate it on a Linux Machine. It started behaving weirdly. So I have this feeling that It can be a Chrome Driver-related issue.
When I send a URL like this:
l.send_keys("https://google.com")
But becomes:
/google.comhttps:
Then I tried to debug this behavior by sending the following:
>>> l.send_keys("/") # /|
>>> l.send_keys("/") # |/
So the position of the cursor is going ahead of the line for the second /. I was not expecting this. I wonder if you can shed light on how to solve this?
Possibly you are trying to invoke send_keys() too early within the <input> field even before the element have rendered properly.
Solution
Ideally to send a character sequence to the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "element_css_locator"))).send_keys("https://google.com")
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
I'm using Selenium in a project that consists of opening a range of websites, that contains pretty much the same structure, collecting data in each site and storing it.
The problem I ran into is that some of the sites I wan't to access are unavailable, and when the program get to one of those it just stops.
What I want it to do, is to skip those and follow on with the next iterations, but so far my tries have been obsolete... In my latest try I used the method is_displayed(), but apparently it will only tell me if an element is visible or not, instead of telling me if it's present or not.
if driver.find_element_by_xpath('//*[#id="main-2"]/div[2]/div[1]/div[1]/div/div[1]/strong').is_displayed():
The example above doesn't work, because the driver needs to find the element before telling me if it visible or not, but the element is simply not there.
Have any of you dealt with something similar?
How one of the sites looks like normally
How it looks like when it is unavailable
You can use Selenium expected conditions waiting for element presence.
I'm just giving an example below.
I have defined the timeout for 5 seconds here, but you can use any timeout value.
Also, your element locator looks bad.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element_xpath_locator = '//*[#id="main-2"]/div[2]/div[1]/div[1]/div/div[1]/strong'
wait = WebDriverWait(browser, 5)
wait.until(EC.presence_of_element_located((By.XPATH, element_xpath_locator)))
I am trying to write a program using Selenium WebScraping to interact with my email. The code I pasted below is just for the login process. I changed the email and password.
from selenium import webdriver
#Edge
driver = webdriver.Chrome()
#Open the website
driver.get('https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=13&ct=1602431674&rver=7.0.6737.0&wp=MBI_SSL&wreply=https%3a%2f%2foutlook.live.com%2fowa%2f%3fnlp%3d1%26RpsCsrfState%3d2c3ee82f-9893-34e5-fd04-e3b4c3e2ccc4&id=292841&aadredir=1&CBCXT=out&lw=1&fl=dob%2cflname%2cwld&cobrandid=90015')
log_in_button = driver.find_element_by_name("loginfmt")
log_in_button.send_keys('myemail#outlook.com')
next_button = driver.find_element_by_id("idSIButton9")
next_button.click()
password_button = driver.find_element_by_name("passwd")
password_button.send_keys('my_password')
When I run this however (with the right email and password), the program cannot seem to enter the password at the last step. There is no error log, and my program enters my email just fine, but it cannot enter the password. I tried using several different ways to locate the HTML element including
find_element_by_type()
find_element_by_id()
find_element_by_class_name()
and also
find_element_by_css_selector()
Most of these methods ended up with StaleElementReferenceException, some ended up with Cannot Locate Element, and the rest didn't work at all.
Does anyone know a method to typing in a password via Selenium, I am assuming that either I am using the wrong element, or Microsoft purposely blocks this kind of behavior for some reason.
Any help is greatlly appreciated. Thanks.
The best practice is to avoid time.sleep() wherever possible. time.sleep() unnecessary slow down your scrpits.
Best practice says always use Explicit wait to avoid synchronization issue.
Use WebDriverWait() and wait for element_to_be_clickable()
password_button =WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.NAME,"passwd")))
You need to import below libraries.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Further learning you can refer below Explicit Waits
I am new to selenium in python (and all web-interface applications of python) and I have a task to complete for my present internship.
My script successfully navigates to an online database and inputs information from my data tables, but then the webpage in question takes anywhere from 30 seconds to several minutes to compute an output.
How do I go about instructing python to re-check the page every 30 seconds until the output appears so that I can parse it for the data I need? For instance, which functions might be I start with?
This will be part of a loop repeated for over 200 entries, and hundreds more if I am successful so it is worth my time to automate it.
Thanks
You should use Seleniums Waits as pointed by G_M and Sam Holloway.
One which I most use is the expected_conditions:
from selenium import webdriver
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.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
It will wait until there is an element with id "myDynamicElement" and then execute the try block, which should contain the rest of your work.
I prefer to use the the class By.XPATH, but if you use By.XPATH with the method presence_of_element_located add another () so it will be the required tuple as noted in this answer:
from selenium.webdriver.common.by import By
driver.find_element(By.XPATH, '//button[contains(text(),"Some text")]')
driver.find_element(By.XPATH, '//div[#id="id1"]')
driver.find_elements(By.XPATH, '//a')
The easiest way to find (for me) the XPATH of an element is going to the developer mode in chrome (F12), pressing ctrl+F, and using the mouse with inspect, trying to compose the proper XPATH, which will be specific enough to find just the expected element, or the least number of elements as possible.
All the examples are from (or based) the great selenium documentation.
If you just want to space out checks, the time.sleep() function should work.
However, as G_M's comment says, you should look into Selenium waits. Think about this: is there an element on the page that will indicate that the result is loaded? If so, use a Selenium wait on that element to make sure your program is only pausing until the result is loaded and not wasting any time afterwards.
I am getting some very odd behavior on a project. Essentially this automation creates an article on a web page using selenium and verifies it's existence by clicking/opening the article. However when i run the program without debug it is failing to "click()" on the web element. So I investigate and start to debug. I notice that the web element ("target_element") is "None". I continue past for just debugging and it fails to click "target_element" as expected.
When i rerun the program and instead of continuing on i open the class in the debug view. I see that "target_element" exists, so i continue on and target_element.click() successfully loads the article on the webpage. Does anyone have any suggestions on how to fix this problem?
TLDR; article.target_element does not exist when running the program UNLESS i set a breakpoint and look at "article" in the debugger. Then if i continue in the program article.target_element suddenly exists.
Possible reason is the element load time.
When you are running the test Selenium runs faster than the time needed by the element to load properly and eventually throws the exception. On the other hand, during debug you are stepping in and giving enough time for the element to load and Selenium finds the element without any issue.
If, the problem is exactly what it is mentioned above the use of explicit wait should be the way to go.
Example taken from the Selenium Python doc
from selenium import webdriver
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.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()