I have a wait code for one of the items I need:
WebDriverWait(driver, 5).until(lambda driver: driver.find_elements(
By.XPATH, 'XPATH') or driver.find_elements(
By.XPATH, 'XPATH') or driver.find_elements(
By.XPATH, 'XPATH'))
Can I somehow find out which element I waited for?
I know that I can check for the existence of these elements like this:
if driver.find_elements(By.XPATH, 'XPATH') > 0:
True
elif driver.find_elements(By.XPATH, 'XPATH') > 0:
True
But it is not as beautiful as I want. I am interested in the possibility of identification inside the until function.
If you have any other ideas I would love to hear them out.
In Python, and operator works in special way.
Try this:
WebDriverWait(driver, 5).until(lambda driver: (driver.find_elements(
By.XPATH, 'XPATH1') and 1) or (driver.find_elements(
By.XPATH, 'XPATH2') and 2) or (driver.find_elements(
By.XPATH, 'XPATH3') and 3))
This will return 1, 2 or 3 based on which XPATH was found. You can replace these numbers with any String/expression as well. Only condition is it should be an expression which can pass if (expression) in python.
Related
I'm using python with selenium to access a webpage. And I want to keep checking rather the element's text exist. Only if it exist then the loop stopped. I come up with some code like:
while True:
try:
myElem = WebDriverWait(driver, 0).until(EC.presence_of_element_located((By.XPATH, '//*[#id="EP"]/ol/li/li')))
if(myElem.text == "HELLO"):
print("Found!")
except TimeoutException:
print("Not Found!")
continue
break
Now, the main issue is instead of 1 element. I need to check 3 elements. If any one of the element was found. Then print the found element and stop the loop. How can I achieved this?
WebDriverWait(driver, 0).until(EC.presence_of_element_located((By.XPATH, '//*[#id="EP"]/ol/li/li')))
WebDriverWait(driver, 0).until(EC.presence_of_element_located((By.XPATH, '//*[#id="EP"]/div[2]/p[2]/p[2]')))
WebDriverWait(driver, 0).until(EC.presence_of_element_located((By.XPATH, '//*[#class="class20"]')))
python: 3.11.1, selenium: 4.8.0
Put the try...except... in a function which takes as parameters the element's xpath and text, and returns True if text is found, otherwise False. Then loop and check if any of the three calls returned True.
from selenium.common.exceptions import TimeoutException
def check_presence(xpath, txt):
try:
myElem = WebDriverWait(driver, 0).until(EC.presence_of_element_located((By.XPATH, xpath)))
if myElem.text == txt:
print("Found!",txt)
return True
else:
print(f'Element exists but text "{txt}" does not match')
except TimeoutException:
print("Not Found!",txt)
return False
while 1:
a = check_presence('//*[#id="EP"]/ol/li/li' , "HELLO")
b = check_presence('//*[#id="EP"]/div[2]/p[2]/p[2]' , "HI")
c = check_presence('//*[#class="class20"]' , "CIAO")
if any([a,b,c]):
break
The easiest way to do this is to combine the different XPaths into one and check for the existence of "HELLO" in the XPath itself.
//*[#id="EP"]/ol/li/li[text()="HELLO"] | //*[#class="class20"][text()="HELLO"] | //*[#id="EP"]/div[2]/p[2]/p[2][text()="HELLO"]
If any element is returned, you've found a desired element. You put this in a wait with a reasonable timeout (30s?) and you're done.
try:
myElem = WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH, '//*[#id="EP"]/ol/li/li[text()="HELLO"] | //*[#class="class20"][text()="HELLO"] | //*[#id="EP"]/div[2]/p[2]/p[2][text()="HELLO"]')))
print("Found!")
except TimeoutException:
print("Not Found!")
NOTE: I don't think //*[#id="EP"]/ol/li/li and //*[#id="EP"]/div[2]/p[2]/p[2] are valid locators. You can't have nested LI or P tags in valid HTML. You might want to check those again and update them.
I am uploading an image, and I used time.sleep(3) to make it finish upload. But sometimes 3 seconds isn't enough. I am not sure how the code should look like to make slenium to check for a specific tag is shown, then continue to do something.
#input image path
try:
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "/html/body/table[2]/tbody/tr[2]/td/h5/ul/li[1]/div[2]/ul/li/form[1]/input[5]")))
element.send_keys('C:\\1.png')
print("Add actionImageURL 1: " + str(element.get_attribute('value')))
except Exception:
print("actionImageURL 1 Path Failed")
#click upload button
try:
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "/html/body/table[2]/tbody/tr[2]/td/h5/ul/li[1]/div[2]/ul/li/form[1]/input[6]")))
element.click()
print("actionImageURL 1 Uploading...")
#maybe here is where i can do find for the tag and do a loop wait?
images = driver.find_elements_by_class_name('img-thumbnail ng-hide')
previewlink = images.get_attribute('src')
print(previewlink)
if preview == 't.notInPlaceActionImageURL_preview':
print('Link: ' + print(previewlink))
time.sleep(3)
print("actionImageURL 1 Uploaded")
except Exception:
print("actionImageURL 1 Upload Button NOT FOUND")
I do not know how to deal with html tag like this, see before and after when image is done uploading:
Before:
After:
implicit might solve my problem, but i am looking to workaround with the tag, and how do deal with tag like those. Thanks
If you code a method to wait you can use that wait method in your project
private static WebElement waitForElement(By locator, int timeout)
{
WebElement element=new WebDriverWait(driver,timeout).until(ExpectedConditions.presenceOfElementLocated(locator));
return element;
}
The above code is wait method
If you want to use this method
waitForElement(By.xpath("//button[#type='submit']"),50);
This for example ,you can use your web element here
This question already has answers here:
How to get text with Selenium WebDriver in Python
(9 answers)
Closed 3 years ago.
i try to get the content of
<span class="noactive">0 Jours restants</span>
(which is the expiration date of the warranty)
but i don't know how to get it (i need to print it in a file)
my code
def scrapper_lenovo(file, line):
CHROME_PATH = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
CHROMEDRIVER_PATH = 'C:\webdriver\chromedriver'
WINDOW_SIZE = "1920,1080"
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=%s" % WINDOW_SIZE)
chrome_options.binary_location = CHROME_PATH
d = driver.Chrome(executable_path=CHROMEDRIVER_PATH,
chrome_options=chrome_options)
d.get("https://pcsupport.lenovo.com/fr/fr/warrantylookup")
search_bar = d.find_element_by_xpath('//*[#id="input_sn"]')
search_bar.send_keys(line[19])
search_bar.send_keys(Keys.RETURN)
time.sleep(4)
try:
warrant = d.find_element_by_xpath('//*[#id="W-Warranties"]/section/div/div/div[1]/div[1]/div[1]/p[1]/span')
file.write(warrant)
except:
print ("test")
pass
if ("In Warranty" not in d.page_source):
file.write(line[3])
file.write("\n")
d.close()
i tried as you can see to print the content of 'warrant' and i couldn't find any function allowing it (i saw some using .text(), .gettext() but for whatever reasons i couldn't get them to work).
You could try explicitly matching the required tag, the relevant XPath expression would be:
//span[#class='noactive']
I would also recommend getting of this time.sleep() function, it's some form of a performance anti-pattern, if you need to wait for presence/visibility/invisibility/absence of a certain element you should rather go for Explicit Wait
So remove these lines:
time.sleep(4)
warrant = d.find_element_by_xpath('//*[#id="W-Warranties"]/section/div/div/div[1]/div[1]/div[1]/p[1]/span')
and use this one instead:
warrant = WebDriverWait(driver, 10).until(expected_conditions.presence_of_element_located((By.XPATH, "//span[#class='noactive']")))
More information: How to use Selenium to test web applications using AJAX technology
I created a loop (while True) to automate a task on the site with python. This code clicks on two fields until an element appears on the page
(browser.find_element_by_id ('formComp: buttonBack').
When this element appears, I want the loop to stop and go to the next block of code.
I tested it that way, but it made a mistake. Python reported that the element "formComp: buttonback" was not found. But that's just it, if not found continue the loop:
while (browser.find_element_by_id('formComp:repeatCompromissoLista:0:tableRealizacao:0:subtableVinculacoes:0:vinculacao_input')):
vinc = wait.until(EC.presence_of_element_located((By.ID, 'formComp:repeatCompromissoLista:0:tableRealizacao:0:subtableVinculacoes:0:vinculacao_input')))
vinc = browser.find_element_by_id('formComp:repeatCompromissoLista:0:tableRealizacao:0:subtableVinculacoes:0:vinculacao_input')
vinc.send_keys('400')
enterElem5 = wait.until(EC.element_to_be_clickable((By.ID, 'formComp:buttonConfirmar')))
enterElem5 = browser.find_element_by_id('formComp:buttonConfirmar')
enterElem5.send_keys(Keys.ENTER)
time.sleep(int(segundosv))
if (browser.find_element_by_id('formComp:buttonRetornar')== True):
break
else:
continue
Try like this hope this helps.Check the length count of the button more than 0.
if (len(browser.find_elements_by_id('formComp:buttonRetornar'))>0):
break
else:
continue
find_element_by_id() does not return False when an element is not found. Instead, it raises selenium.common.exceptions.NoSuchElementException. You can handle the exception to get the flow control you are looking for:
try:
browser.find_element_by_id('formComp:buttonRetornar')
break
except NoSuchElementException:
continue
import time
from selenium import webdriver
webdriver.Chrome('/Users/name/PycharmProjects/untitled15/chromedriver')
driver.get('http://www.google.com/xhtml')
time.sleep(2)
search_box = driver.find_element_by_name('q')
search_box.send_keys('keywordtosearch')
search_box.submit()
time_sleep(10)
driver.quit()
this is what so far I have obtained. I want to get top x searches from google for any given keyword
please assist me with this. Thank you!
I did a similar mini-project, where:
to get results by their respective links:
results_list = browser.find_elements_by_tag_name('a')
to simply loop through results and print them out:
i=0
for item in results_list:
print (item.get_attribute('href'), '\n')
if i == 10:
break
else:
i+=1
Hope this helps! Good luck.