Python Selenium: How to wait until href attribute contains a specific string? - python

For example, I'm opening page https://example.com/page-1/ in Selenium, looking for a specific link that contains domain.com. Right now I'm using sleep(20) to ensure the page has fully loaded. But I wonder if I can use WebDriverWait not only for tag presence but also for its contains presence as well. Could not find any solution yet...

You can try something like this, I'm assuming that you are using Firefox but the logic is the same:
firefox = webdriver.Firefox()
firefox.get('https://example.com/page-1/')
#wait for a maximum of 60 seconds in this example
wait = WebDriverWait(firefox, 60)
domain = "domain.com"
wait.until(lambda x: x.find_element_by_css_selector(f"a[href*='{domain}']"))

To wait for the WebElement for the href attribute to contain a specific string, you can induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Full match of domain.com:
Using CSS_SELECTOR:
element = WebDriverWait(browser, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "a[href='domain.com']")))
Using XPATH:
element = WebDriverWait(browser, 20).until(EC.visibility_of_element_located((By.XPATH, "//a[#href='domain.com']")))
Partial match of domain.com:
Using CSS_SELECTOR:
element = WebDriverWait(browser, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "a[href*='domain.com']")))
Using XPATH:
element = WebDriverWait(browser, 20).until(EC.visibility_of_element_located((By.XPATH, "//a[contains(#href, 'domain.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

Related

No such element error but the element can be located in the DOM through xpath expression

I have a python script logging into our company website to then get each row of data. It logs me in, locates the iframe where the table with row values is located, from there I try to locate a row in the iframe table and attached is a picture:
Highlighting the correct xpath expression but I need all 31 values.
All my code works properly except this:
elem5 = browser.find_element_by_xpath("//td/label[contains(#id, 'driver')][1]")
find_element_by_* returns a single webelement, where as you are looking for all the 31 elements. So you need find_elements* and you can use either of the following Locator Strategies:
Using css_selector:
elements = driver.find_elements(By.CSS_SELECTOR, "td > label[id^='driver']")
Using xpath:
elements = driver.find_elements(By.XPATH, "//td/label[starts-with(#id, 'driver')]")
To find all the desired elements ideally you need to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "td > label[id^='driver']")))
Using XPATH:
elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//td/label[starts-with(#id, 'driver')]")))
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

Python Selenium get "sold items" information from eBay Productpage

I want to click on the following element "23 verkauft" on an eBay productpage you can see it on this screenshot:
Here is the HTMl Code of this Element:
Here is my Code but the webdriver cant locate the element or can't click on it.
sold = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//span[#class, 'vi-txt-underline']")))
sold.click()
You were close enough. But you have to make to adjustments:
Instead of (By.XPATH, "//span[#class, 'vi-txt-underline']") you need to use (By.XPATH, "//span[#class='vi-txt-underline']")
Instead of presence_of_element_located() you need to use element_to_be_clickable()
Solution
To click on the element with text as 23 verkauft you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using LINK_TEXT:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.LINK_TEXT, "23 verkauft"))).click()
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a.vi-txt-underline"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[text()='23 verkauft']"))).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
You have an error with your locator.
Instead of
//span[#class, 'vi-txt-underline']
It should be
//a[#class='vi-txt-underline']
Also instead of presence_of_element_located you should use visibility_of_element_located since the former method will wait for more mature element state, not only presented on the page but also visible.
Also you can click on the element there directly, no need for the additional code line.
So your code could be
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//a[#class='vi-txt-underline']"))).click()

Python Selenium - find item in a list

I have the following:
Aliases
NAT
Rules
I can't seem to be able to locate the element with text Aliases. Is it possible to do?
Can anyone help me out?
You can use like:
//*[text()="Aliases"]
another way is
//a[#href="/firewall_aliases.php" and (text()="Aliases")]
You can use the following XPath locator:
//a[text()="Aliases"]
For more uniqueness you can use
//a[#href="/firewall_aliases.php" and (text()="Aliases")]
Or even
//a[#href="/firewall_aliases.php" and (#class="navlnk") and (text()="Aliases")]
To locate the element with text as Aliases you can use either of the following Locator Strategies:
Using link_text:
element = driver.find_element(By.LINK_TEXT, "Aliases")
Using css_selector:
element = driver.find_element(By.CSS_SELECTOR, "a.navlnk[href*='firewall_aliases']")
Using xpath:
element = driver.find_element(By.XPATH, "//a[text()='Aliases' and contains(#href, 'firewall_aliases')]")
Ideally, to locate the element you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using LINK_TEXT:
element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.LINK_TEXT, "Aliases")))
Using CSS_SELECTOR:
element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "a.navlnk[href*='firewall_aliases']")))
Using XPATH:
element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//a[text()='Aliases' and contains(#href, 'firewall_aliases')]")))
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

Unable to reliably select element regardless of method using Selenium

I'm trying to select the "Majors" button on [this webpage] (https://www.dukascopy.com/swiss/english/marketwatch/historical/)
I am able to switch into the iframe where this element is contained, but trying to click by using the xpath, id or class name of the element all result in a seemingly random button within the same column being selected. Below is the current code I'm using along with a screenshot of inspection of the button.
majorforexbutton = driver.find_element_by_xpath('/html/body/div[9]/div[1]/div[3]/ul/li[4]')
majorforexbutton.click()
screenshot:
The element with text as Majors field is within a <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
driver.get('https://www.dukascopy.com/swiss/english/marketwatch/historical/')
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[src*='freeserv.dukascopy.com/2.0/?path=historical_data_feed']")))
driver.execute_script("return arguments[0].scrollIntoView(true);", WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Instrument']"))))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "li[data-group='FX_MAJORS'][data-parent='FX']"))).click()
Using XPATH:
driver.get('https://www.dukascopy.com/swiss/english/marketwatch/historical/')
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,"//iframe[contains(#src, 'freeserv.dukascopy.com/2.0/?path=historical_data_feed')]")))
driver.execute_script("return arguments[0].scrollIntoView(true);", WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Instrument']"))))
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//li[text()='Majors']"))).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
Browser Snapshot:
Reference
You can find a couple of relevant discussions in:
Ways to deal with #document under iframe
Switch to an iframe through Selenium and python
Try grabbing your element and trying either one of the bottom.
elem = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.ID, ":5x")))
1 of these:
elem.click()
driver.execute_script("arguments[0].click();", elem)

Python/Selenium Click on an element in a ul

I am new to Python/Selenium (< 3 days). I am trying to click on the "grades" item of an unordered list (Please see image). I have tried find_element_by_link_text, find_element_by_css_selector but am unable to find it.
Image from inspect element
Thanks.
As per the HTML it is pretty clear that the desired field is within an <iframe> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"frameDetail")))
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a#grades")))
Using XPATH:
WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.ID,"frameDetail")))
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[#id='grades']")))
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
Reference
You can find a couple of relevant discussions in:
Ways to deal with #document under iframe
Switch to an iframe through Selenium and python

Categories

Resources