Try alternative xpaths, or else continue - python

I have pieced together a web crawler with Selenium that uses XPath to find elements. On the web page I'm scraping, there are two possible layouts that are loaded, depending on the content.
If I run my code on the wrong layout, I get the error: Message: Unable to locate element: {"method":"xpath","selector":
How can I create a try/except (or similar) that tries an alternative xpath, if the first xpath is not present? Or if none is present, continue on to the next section of code?

I haven't got experience with Python so I'm not able to write you an example code, but you should create two try/catch (or in this case try/except) block where you try to find your element with find_element_by_xpath. After that catch the NoSuchElementException and you can work with the WebElement(s).
In JAVA it looks something like this:
Boolean isFirstElementExist, isSecondElementExist = true;
WebElement firstElement, secondElement;
try {
firstElement = driver.findElement(By.xpath("first xpath"));
} catch (NoSuchElementException e) {
isFirstElementExist = false;
}
try {
secondElement = driver.findElement(By.xpath("second xpath"));
} catch (NoSuchElementException e) {
isSecondElementExist = false;
}
//... work with the WebElement

Here is the simple solution:
try:
element_in_layout_1 = driver.find_element_by_xpath("my_xpath_1")
except:
try:
element_in_layout_2 = driver.find_element_by_xpath("my_xpath_2")
except:
print "No Element was found"
pass
else:
print "Element in Layout 2 was found"
else:
print "Element in Layout 1 was found"

Related

IF ELSE Statement in python selenium webdriver not executing Else when element is not there

I am using an automation script with selenium web driver. It usually works fine, but sometimes the content on a page is changing.
If the element it is looking for is not there, it is crashing instead of executing the else statement.
I Tried to use another function with try and NoSuchElementException, but I do get another error about NoSuchElementException.
This is the if else statement:
#Look for link text "Stores"
find_store = driver.find_element_by_link_text('Stores')
if find_store:
find_store.click()
else:
driver.get("https://example.com/myaccount")
time.sleep(5)
This is the try statement:
try:
find_store = driver.find_element_by_link_text('Stores')
if find_store.is_displayed():
find_store.click() # this will click the element if it is there
print("Store found, all good.")
except NoSuchElementException:
driver.get("https://example.com/myaccount")
print("Store was not found, visiting base URL to search for store")
time.slep(5)
In the first script I expect it to search for the element. If its not there, then visit the URL so I can search for the element there. But it never opens the URL and I get this error:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element:
In the second script I expect to look for the element. If the element is not there, it should visit the base url and try again later in the code. However here I get this error:
except NoSuchElementException:
NameError: name 'NoSuchElementException' is not defined
I would like to learn how I can avoid the script crashing and actually execute an alternative action if the element is not there. Thank you.
Use Following :
if len(driver.find_elements_by_link_text('Stores'))> 0:
driver.find_element_by_link_text('Stores').click()
else:
driver.get("https://example.com/myaccount")
time.sleep(5)

Until/WebDriverWait throwing NoSuchElementException

Based on every answer and piece of documentation I've seen, the following should wait for the element at xpath path:
delay = some amount of time way longer than I know is needed
driver = webdriver.Firefox()
driver.get(url)
wait = WebDriverWait(driver, delay, ignored_exceptions=NoSuchElementException)
wait.until(EC.presence_of_element_located(driver.find_element_by_xpath(path)))
but no matter what I do it always throws a NoSuchElementException immediately after getting the url. And before anyone marks this as a duplicate or calls me out on it, I am aware of this answer and although the element I'm looking for is in some kind of wrapper, I got the same problem when trying the above looking for that wrapper instead (also it works if I just provide a normal sleep call instead of the Expected Condition stuff which makes me think I don't need to manually enter into the wrapper). What's the point of having a function for waiting for an element to be loaded that doesn't wait until the element is loaded? Any help in solving this problem would be greatly appreciated.
I use this java code for similar situations:
private Wait<WebDriver> staleWait = new FluentWait<>(getDriver())
.withTimeout(WAIT_INTERVAL, TimeUnit.SECONDS)
.pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
protected WebElement visibilityOf(WebElement webElement) {
staleWait.until((ExpectedCondition<Boolean>) webDriver -> {
try {
return element(webElement).isDisplayed();
} catch (StaleElementReferenceException e) {
return false;
} catch (NoSuchElementException ne) {
return false;
}
});
return element(webElement);
}

Issue with the payment flow using selenium webdriver and Python

I have a scenario where I need to automate the payment page.
I need to enter the credit card details, but the thing is when I use send_keys method to type the text, it doesn't take the full card number though it only takes the first three characters and the last one.
This is the code:
elem = driver.find_element_by_id("checkout_credit_card_number")
elem.send_keys(str(sys.argv[5]), Keys.ARROW_DOWN)
elem = driver.find_element_by_id("checkout_credit_card_name")
elem.send_keys(str(sys.argv[6]))
elem = driver.find_element_by_id("checkout_credit_card_month")
elem.send_keys(str(sys.argv[7]))
elem = driver.find_element_by_id("checkout_credit_card_year")
elem.send_keys(str(sys.argv[8]))
elem = driver.find_element_by_id("checkout_credit_card_verification_value")
elem.send_keys(str(sys.argv[9]), Keys.ARROW_DOWN)
I read that one solution is to inject the credit card number with Javascript, basically something like execute_script with a string and argument. All has to be in Python.
Any ideas how to do that?
change in to python it should be the same
public void runScript(Driver driver, String script) {
JavascriptExecutor js = null;
if (driver instanceof JavascriptExecutor) {
js = (JavascriptExecutor) driver;
try {
logger.info(script);
js.executeScript(script);
} catch (Exception e) {
logger.info(e + " " + script);
}
}
}

How can I click button or div tag dynamically until it disappear from page using selenium python?

Using this link I want all reviews from that page.
I have used xpaths(given in sample code) to click load more until it disappear from that page,but my solution fails and giving following errors.
Error- Message: Element is no longer attached to the DOM Stacktrace
or
in _read_status
raise BadStatusLine(line)
httplib.BadStatusLine: ''
Sample Code with xpaths
Either
driver.execute_script('$("div.load-more").click();')
or
xpath_content='//div[#class = "load-more"]'
driver.find_element_by_xpath(xpath_content).click()
Is there any solution which may not fail in any case? How can I click on load more until it disappear form that page or Is there any other way to get all reviews from this page?
One more thing I am using firepath to generate review's xpath which is .//*[#id='reviews-container']/div1/div[3]/div1/div/div/div[3]/div/div1/div
Is there a way to get our own xpath instead using firepath?
This is a java solution for your problem. You can use the same logic for python as well
public static void loadAll(WebDriver driver) {
while (true) {
//Using findElements to get list of elements so that it wont throw exception if element is not present
List<WebElement> elements = driver.findElements(By.xpath("//div[#class='load-more']"));
//If the size is zero that means load more element is not present so breaking the loop
if (elements.isEmpty()) {
break;
}
//Assigning first element to a variable
WebElement loadEl = elements.get(0);
//Getting text of element
String text = loadEl.getText().toLowerCase();
//check if text contains load more, as, if it is loading it will have ... ,so we cant click at that time
if (text.contains("load more")) {
loadEl.click();
}
//if text contains 1 to 4 means [for ex "Load More 4"] this is the last click so breaking the loop
if (text.matches("load more [1-4]")) {
break;
}
}
System.out.println("Done");
}

Unable to perform click action in selenium python

I'm writing a test script using selenium in python. I have a web-page containing a tree-view object like this:
I want to traverse over the menu to go to the desired directory. Respective HTML code for plus/minus indications is this:
<a onclick="changeTree('tree', 'close.gif', 'open.gif');">
<img id="someid" src="open.gif" />
</a>
The src attribute of the image can be either open.gif or close.gif.
I can detect weather there is a plus or minus by simply checking the src attribute of the img tag. I can also easily access to the parent tag, a, by using .find_element_by_xpath("..").
The problem is that I can't perform the click action not on the img nor the a tag.
I'v tried webdriver.Actions(driver).move_to_element(el).click().perform(); but it did not work.
I think I should mention that there is no problem in accessing the elements, since I can print all their attributes; I just can't perform actions on them. Any help?
EDIT 1:
Here's the js code for collapsing and expanding the tree:
function changeTree(tree, image1, image2) {
if (!isTreeviewLocked(tree)) {
var image = document.getElementById("treeViewImage" + tree);
if (image.src.indexOf(image1)!=-1) {
image.src = image2;
} else {
image.src = image1;
}
if (document.getElementById("treeView" + tree).innerHTML == "") {
return true;
} else {
changeMenu("treeView" + tree);
return false;
}
} else {
return false;
}
}
EDIT 2:
I Googled for some hours and I found out that there is a problem about triggering the Javascript events and the click action from web-driver. Additionally I have a span tag in my web-page that has an onclick event and I also have this problem on it.
After some tries like .execute_script("changeTree();"), .submit(), etc, I have solved the issue by using the ActionChains class. Now, I can click in all elements that they have java-script events as onclick. The code that I have used is this:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('someURL')
el = driver.find_element_by_id("someid")
webdriver.ActionChains(driver).move_to_element(el).click(el).perform()
I don't know if it occurred just to me or what, but I found out that I should find the element right before the key command; otherwise the script does not perform the action. I think it would be related to staling elements or something like that; anyway, thanks all for their attention.

Categories