How do i make explicit wait check for page source - python

This is just an example, but I want if Hello in html source on explicit wait, how do I make it work?
if "Hello" in html_source:
WebDriverWait wait = new WebDriverWait(driver,10)
wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("foobar")))

From selenium documentation
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:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//*[text()='Hello']")))
print(driver.page_source)
except:
print("element could not be found within the 10 second timeout period")
If you want a better answer, I suggest you ask a better question and use examples.

Related

Selenium Python find_element Xpath cant find xpath

I want to access an website with selenium and than a addblock-window appears, in which i need to click a button for it to disappear.
Eventhough I can find my XPath(//button[#title='Einverstanden'], /html/body/div/div[2]/div[3]/div[1]/button[#title = 'Einverstanden'] or
//button[contains(text(),"Einverstanden")]') in the browser,
I can't find it with my Python script. And i can't seem to find the mistake.
Here is my code.
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.implicitly_wait(30)
driver.get("``https://www.derstandard.at/story/2000134260361/endspiel-vor-gericht-prozess-gegen-boris-becker-startet-in-london``")
driver.maximize_window()
x = driver.find_element(By.XPATH, "//button[#title = 'Einverstanden']")
print(x)
This is the error I'm getting.
The button is enclosed in an iframe in which case, you first need to switch to the iframe and then access the element
This should work:
driver.get("https://www.derstandard.at/consent/tcf/")
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH, "//div[contains(#id, 'sp_message_container')]//iframe")))
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button[title='Einverstanden']"))).click()
Wait Imports:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
In case you want to switch to default frame again, you may use this when required:
driver.switch_to.default_content()

Python selenium can't locate element since it is not in the source code

I am trying to get the date that is highlighted in the calendar from https://web.archive.org/web/20110101000000*/area51.stackexchange.com
I can see the "calendar-day" class in chrome inspector but it is not displayed in the source code.
I have also tried to locate other class elements such as "month-week" but failed. Can anyone help me to diagnose what the problem is? I have looked into ShadowDOM but it seems not to be the issue here (I might be wrong though).
Furthermore, I am also trying to get the url "/web/20110430/area51.stackexchange.com" but don't know how to locate by class, tag name, css or Xpath.
driver = webdriver.Firefox()
driver.get("https://web.archive.org/web/20110101000000*/area51.stackexchange.com")
element=driver.find_element_by_class_name("calendar-day")
Thanks in advance!
Simply wait for the div element of calender to come up and print it. Your class name had an extra space as well as taking some time after a page loads.
element=WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, "//div[contains(#class,'calendar-day')]")))
print(element.text)
Outputs 11
To grab multiple
elements=WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//div[contains(#class,'calendar-day')]")))
for element in elements:
print(element.text)
Outputs
11
30
7
16
18
10
11
7
12
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
The page you are using is taking a while to load, so it will be better if you introduce some explicit wait before extracting.
A sample script can be:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("https://web.archive.org/web/20110101000000*/area51.stackexchange.com")
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "calendar-day ")))
print(element.text)
driver.quit()
To extract multiple element just need to add/change WebDriverWait(driver, 20).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "calendar-day ")))
So updated sample script can be
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("https://web.archive.org/web/20110101000000*/area51.stackexchange.com")
wait = WebDriverWait(driver, 10)
element = wait.(driver,20).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "calendar-day ")))`
for el in element:
print(el.text)
driver.quit()

Can't click on a grid with the absence of some hardcoded delay

I'm trying to click on Jetzt bewerben available in this webpage using selenium. The script that I've written so far can click on that grid If I stick with hardcoded delay. I would like to do the clicking without using any hardcoded delay.
I've tried with:
import time
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
url = "https://jobs.deloitte.de/job/D%C3%BCsseldorf-Werkstudent-%28mwd%29-Administration-Business-Process-Solutions/522320501/"
driver = webdriver.Chrome()
driver.get(url)
wait = WebDriverWait(driver,10)
time.sleep(5)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR,"a#bewerben_top > h1"))).click()
How can I click on that grid shaking off hardcoded delay?
There is not a problem with a fact that button is not clickable or not visible.
The problem is that there is Javascript doing some "magic" to the button.
All you need to do is to wait until the document is complete.
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
url = "https://jobs.deloitte.de/job/D%C3%BCsseldorf-Werkstudent-%28mwd%29-Administration-Business-Process-Solutions/522320501/"
driver = webdriver.Chrome()
driver.get(url)
wait = WebDriverWait(driver,10)
wait.until(lambda d: d.execute_script("return document.readyState")=='complete')
driver.find_element_by_css_selector("a#bewerben_top > h1").click()
Your locator strategy was perfect. However, there are a couple of things:
It seems the Browsing Context of the website https://jobs.deloitte.de/job/D%C3%BCsseldorf-Werkstudent-%28mwd%29-Administration-Business-Process-Solutions/522320501/ returns back the control even before document.readyState turns complete.
Ideally, you should acknowledge the Acceptance of the website's cookie policy.
As per best practices, while invoking click() you need to induce WebDriverWait for the element_to_be_clickable().
You can use the following Locator Strategies:
driver.get("https://jobs.deloitte.de/job/D%C3%BCsseldorf-Werkstudent-%28mwd%29-Administration-Business-Process-Solutions/522320501/")
WebDriverWait(driver, 10).until(lambda driver: driver.execute_script('return document.readyState') == 'complete')
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button#cookie-acknowledge"))).click()
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a#bewerben_top > h1"))).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
PS: In such one off scenarios you may require to wait for the jQuery to complete as follows:
WebDriverWait(driver, 20).until(lambda driver: driver.execute_script('return jQuery.active') == 0)

Selenium Python Script throws no element error exception even though the x path is right?

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
driver=webdriver.Chrome()
driver.get("https://paytm.com/")
driver.maximize_window()
driver.find_element_by_class_name("login").click()
driver.implicitly_wait(10)
driver.find_element_by_xpath("//md-input-container[#class='md-default-theme md-input-invalid']/input[#id='input_0']").send_keys("99991221212")
In the above code, I have verified the xpath using fire bug its highlighting the correct element. But when the script run its failing? Can you help me folks?
In selenium each frame is treated individually. Since the login is in a separate iframe element, you need to switch to it first using:
iframe = driver.find_elements_by_tag_name('iframe')[0]
driver.switch_to_frame(iframe)
Before trying to interact with it's elements.
Or in this case, you would wait for the frame to exist, and it would be:
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.Chrome()
driver.get("https://paytm.com/")
driver.maximize_window()
wait = WebDriverWait(driver, 10)
wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "login"))).click()
wait.until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe")))
_input = wait.until(EC.visibility_of_element_located((By.ID,"input_0")))
_input.send_keys("99991221212")
You should try using WebDriverWait to wait until input element visible on the page as below :-
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()
driver.get("https://paytm.com/")
driver.maximize_window()
wait = WebDriverWait(driver, 10)
wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "login"))).click()
#now switch to iframe first
wait.until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe")))
input = wait.until(EC.visibility_of_element_located((By.ID, "input_0")))
input.send_keys("99991221212")
Hope it helps...:)

What is the best way to check URL change with Selenium in Python?

So, what's I want to do is to run a function on a specific webpage (which is a match with my regex).
Right now I'm checking it every second and it works, but I'm sure that there is a better way (as it's flooding that website with getting requests).
while flag:
time.sleep(1)
print(driver.current_url)
if driver.current_url == "mydesiredURL_by_Regex":
time.sleep(1)
myfunction()
I was thinking to do that somehow with WebDriverWait but not really sure how.
This is how I implemented it eventually. Works well for me:
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 5)
desired_url = "https://yourpageaddress"
def wait_for_correct_current_url(desired_url):
wait.until(
lambda driver: driver.current_url == desired_url)
I was thinking to do that somehow with WebDriverWait
Exactly. First of all, see if the built-in Expected Conditions may solve that:
title_is
title_contains
Sample usage:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
wait.until(EC.title_is("title"))
wait.until(EC.title_contains("part of title"))
If not, you can always create a custom Expected Condition to wait for url to match a desired regular expression.
To really know that the URL has changed, you need to know the old one. Using WebDriverWait the implementation in Java would be something like:
wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.not(ExpectedConditions.urlToBe(oldUrl)));
I know the question is for Python, but it's probably easy to translate.
Here is an example using WebdriverWait with expected_conditions:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
url = 'https://example.com/before'
changed_url = 'https://example.com/after'
driver = webdriver.Chrome()
driver.get(url)
# wait up to 10 secs for the url to change or else `TimeOutException` is raised.
WebDriverWait(driver, 10).until(EC.url_changes(changed_url))
Use url_matches Link to match a regex pattern with a url. It does re.search(pattern, url)
from selenium import webdriver
import re
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
pattern='https://www.example.com/'
driver = webdriver.Chrome()
wait = WebDriverWait(driver,10)
wait.until(EC.url_matches(pattern))

Categories

Resources