Selenium script is not consistent - python

I have other examples, but for this specific example what the code does is locate a series of elements that each link to a specific page. Then I click on a specific link. Sometimes this code works, but sometimes it does not work and the page just stays the same without clicking on the link.
I have used a variety of methods like sleep, wait and ActionChains in an attempt to make things more consistent, but it still messes up really frequently.
print(f"No.{i} Opportunity found {optitle_list[i]}")
#click on tender
time.sleep(10)
opentender_button =WebDriverWait(driver,30).until(EC.visibility_of_all_elements_located((By.XPATH,"//img[#src = 'esources/theme/images/view.png']")))
ActionChains(driver).move_to_element(opentender_button[int((j-3)/10)]).double_click().perform()
Here is another example. In this code the keys 'health' are not always sent, resulting in the wrong search options being reviewed by my script.
#Enter into Search box ‘health' and hit "Enter" key
time.sleep(20)
search_box = WebDriverWait(driver,30).until(EC.element_to_be_clickable((By.XPATH,"//label//input[#type='text']")))
ActionChains(driver).move_to_element(search_box).double_click(search_box).send_keys('health').perform()
print("Search box filled")

Related

Python Selenium, edge browser, I dont see Inspect Element on every element

I am trying to get data from a Power Bi table. There are some elements that appear when hovering over a table. When I right click on ... I don't see Inspect Element. However, when I left click on this element, I can see a menu, and if I right click on any items, I can see Inspect element.
My first question, is why I don't see Inspect Element in the right click menu for all elements in the browser. Am I somehow able to open this ... menu programmatically in Selenium?
the Export Data element only appears in HTML after the first left click. I'm assuming this is created using Javascript and in order to export data with Selenium I would have to programmatically instantiate this by clicking on the ... menu. Is selenium capable of triggering javascript functions that generate more html code in a dynamic webpage? Or do I need to somehow click on the ... element.
If I can execute a javascript function, how can I find out in Edge the javascript function that gets executed and how can I replicate this function in Selenium
Essentially, if I try to find the Export data element in Selenium, it is not able to find it, unless I set a breakpoint before search, then in EdgeDriver I open this menu, and then I can find it and click it through Python
If all else fails, can I programmatically open the left click menu by automating a mouse click at certain coordinates in Selenium?
1.1 why I don't see Inspect Element in the right click menu for all elements:
PowerBi has its own context menu so they suppress the browsers context menu. If the element is tricky to find the dev tools, you can press Ctrl + Shift + C (while dev tools is open) and then click the desired element. Your mouse needs to be already over the element before pressing the key combination.
1.2 Am I somehow able to open this ... menu programmatically in Selenium?
Seems a little tricky, but could work if you first find the title of that area and move the mouse there, like described here: https://stackoverflow.com/a/8261754/12914172
Then your element should be in the html and you can find it hopefully by its class name vcMenuBtn that seems to be unique on that page. But you need to verify that.
2. Is selenium capable of triggering javascript functions that generate more html code in a dynamic webpage? Or do I need to somehow click on the ... element.
Selenium is able to execute javascript like desribed here: https://stackoverflow.com/a/70544802/12914172
However in your sample, and I was quickly checking the PowerBI online page, this looks like a whole lot of reverse engineering to understand and can sometimes be dangerous as well. I would go for hoover over the area find the ... and click it.
3. How can I find out in Edge the javascript function that gets executed
In dev tools you can set breakpoints to debug the steps the pages does after an action. But again, I would not invest to much time in that.
4. Can I programmatically open the left click menu by automating a mouse click at certain coordinates in Selenium?
Yes but this never works as good as the way described above. If you still want to give it a try, maybe that answer helps: https://stackoverflow.com/a/26385456/12914172
Many thanks to r000bin, this solution works for me, downloading data from PowerBI using Selenium for Python:
import selenium, mouse, time
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
url = 'https://dataport.gasunie.nl/Vulling-Gasopslagen-Nederland'
driver = selenium.webdriver.Chrome(service=Service())
driver.get(url)
time.sleep(4)
#driver.fullscreen_window()
#driver.switch_to.window(driver.current_window_handle)
time.sleep(4)
iframe = driver.find_elements(By.TAG_NAME, 'iframe')
assert len(iframe)==1
driver.switch_to.frame(iframe[0])
time.sleep(4)
from selenium.webdriver.common.action_chains import ActionChains
actions = ActionChains(driver)
actions.move_to_element_with_offset(driver.find_element(By.TAG_NAME, 'html'), 0,0)
actions.move_by_offset('5', '5').click().perform()
time.sleep(4)
button = driver.find_element(By.CLASS_NAME, 'vcMenuBtn')
button.click()
button = driver.find_element(By.ID, '0')
button.click()
# 4 tabs and 1 enter
time.sleep(4)
for n in range(4):
element = driver.switch_to.active_element
time.sleep(2)
element.send_keys(Keys.TAB)
time.sleep(2)
element = driver.switch_to.active_element
time.sleep(2)
element.send_keys(Keys.ENTER)
driver.close()

Why Selenium couldn't find any element on page before I used time.sleep()?

I came across this problem while automating task with Selenium.
What was the code execution process?
So first of all there're two functions inside seleniumtest.py :
getGateway() and restartRouter().
Let's focus on restartRouter() function as it contains code related to selenium, and getGateway() function was just function that I used in restartRouter() just like this: driver.get(getGateway()).
First of all, what was happening is following:
Start browser and open provided url;
Find elements username and password
Enter username and password;
Find Login element
Click Login;
Find another button
Click on another button
...
What is the problem?
So, the problem start occuring on step 6, just after clicking Login button (See code execution process, step 6).
After it clicks on login button, it loads new page (it doesn't open it in new tab), and after that it didn't want to work.
What have you tried to do to solve the problem
First thing that came up to mine mind was to use driver.wait(5) just after clicking on login, which didn't work.
I've also tried to check if any other element on that page will result in action .click()
After that, I've tried Waits - SELENIUM WAITS ; which also didn't work. I tried two possible options: driver.implicitly_wait(10) and WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,"//*[#id=\"mmManagDiag\"]")). It also gave me errors how my USB Device isn't working while using explicit waits.
None of these worked.
What worked for me?
After working around it came up to my mind to try with time.sleep(3) and suddenly it worked.
My final question
So, I am wondering why Selenium couldn't find any element on that page before I used time.sleep()?
And isn't selenium waits and time.sleep() almost the same thing?
Code
driver = webdriver.Chrome('./chromedriver')
driver.get(getGateway())
#Frm_Username
username = driver.find_element(By.NAME,'Frm_Username')
username.clear()
username.send_keys("user")
#Frm_Password
passwrd = driver.find_element(By.NAME,"Frm_Password")
passwrd.clear()
passwrd.send_keys("user")
#passwrd.send_keys(Keys.RETURN)
driver.find_element(By.XPATH,"//*[#id=\"LoginId\"]").click()
time.sleep(3)
driver.find_element(By.XPATH,"//*[#id=\"mmManagDiag\"]").click()
time.sleep(3)
driver.find_element(By.XPATH,"//*[#id=\"mmManagDevice\"]").click()
time.sleep(3)
driver.find_element(By.XPATH,"//*[#id=\"Btn_restart\"]").click()
time.sleep(3)
driver.find_element(By.XPATH,"//*[#id=\"confirmOK\"]").click()
driver.quit()
Waiting for the elements presence might be not enough to click on it.
Try to wait for element to be clickable.
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "your xpath value"))
).click()

With selenium on python don't know how to shut down a banner which is preventing selenium from accessing the page content

I'm trying to open a site with Selenium (with Python) using Chrome browser, but when I do, a full screen promo banner immediately pops-up and I can't access the site content unless I close it.
On the top right there is an "x" as if it was a quit button, but actually it's an element ::before
and from its description it seems to me that it doesn't contain any button element.
If I operate manually, both clicking on the x and on the upper part of the page outside the banner, the latter closes, but I really don't understand how to access it with selenium.
The webpage I'm trying to open is https://sports.bwin.it/it/sports
Needless to say I'm quite inexperienced, so I hope this question won't sound too basic, but I wasn't able to find a solutione in the selenium docs or on the web; if someone could give me any hint I would appreciate it.
This is a screenshot from the page I'm talking about
This is part of the html code from the web page; the element I am talking about is the one pointed by the arrow;
Based on your screen shot the xpath you want to use would be something like this:
//*[#data-id='dj_sports_c_ovl_br']//span
full code would be something like this:
element = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "//*[#data-id='dj_sports_c_ovl_br']//span"))
)
element.click();

Unable to locate/click pop-up button with Selenium in Python

I'm using Selenium in Python 3 to access webpages, and I want to click on a pop-up button, but I am unable to locate it with Selenium.
What I'm describing below applies to a number of sites with a pop-up, so I'll use a simple example.
url = "https://www.google.co.uk"
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get(url)
The page has a pop-up for agreeing to cookies.
I want the script to click on the "I agree" button, but I'm unable to locate it.
I've found a few questions and posts about this online (including on Stackoverflow), but all the suggestions I found seem to fall in one of the following categories and don't seem to work for me.
Wait longer for the pop-up to actually load.
I've tried adding delays, and in fact, I'm testing this interactively, so I can wait all I want for the page to load before I try to locate the button, but it doesn't make any difference.
Use something like driver.switch_to.alert
I get a NoAlertPresentException. The pop-up doesn't seem to be an alert.
Locate the element using driver.find_element.
This doesn't work either, regardless of which approach I use (xpath, class name, text etc.). I can find elements from the page under the pop-up, but nothing from the pop-up itself. For example,
# Elements in main page (under pop-up)
driver.find_element_by_partial_link_text("Sign in") # returns FirefoxWebElement
driver.find_element_by_class_name("gb_g") # returns FirefoxWebElement
# Elements on the pop-up
driver.find_element_by_partial_link_text("I agree") # NoSuchElementException
driver.find_element_by_class_name("RveJvd snByac") # NoSuchElementException
The popup just doesn't seem to be there in the page source. In fact, if I try looking at the loaded page source from the browser, I can't find anything related to the pop-up. I understand that many sites use client-side scripts to load elements dynamically, so many elements wouldn't show up in the raw source, but that was the point of using Selenium: to load the page, interpret the scripts and access the end result.
So, what am I doing wrong? Where is the pop-up coming from, and how can I access it?

Selenium Python: Census ACS Data- unable to select Download button in window

I am attempting to scrape the Census website for ACS data. I have scripted the whole processes using Selenium except the very last click. I am using Python. I need to click a download button that is in a window that pops when the data is zipped and ready, but I can't seem to identify this button. It also seems that the button might change names based on when it was last run, for example, yui-gen2, yui-gen3, etc so I am thinking I might need to account for this someone. Although I normally only see yui-gen2.
Also, the tag seems to be in a "span" which might be adding to my difficulty honing in on the button I need to click.
Please help if you can shed any light on this for me.
code snippet:
#Refine search results to get tables
driver.find_element_by_id("prodautocomplete").send_keys("S0101")
time.sleep(2)
driver.find_element_by_id("prodsubmit").click()
driver.implicitly_wait(100)
time.sleep(2)
driver.find_element_by_id("check_all_btn_above").click()
driver.implicitly_wait(100)
time.sleep(2)
driver.find_element_by_id("dnld_btn_above").click()
driver.implicitly_wait(100)
driver.find_element_by_id("yui-gen0-button").click()
time.sleep(10)
driver.implicitly_wait(100)
driver.find_element_by_id("yui-gen2-button").click()
enter image description here
enter image description here
Instead of using the element id, which as you pointed out varies, you can use XPath as Nogoseke mentioned or CSS Selector. Be careful to not make the XPath/selector too specific or reliant on changing values, in this case the element id. Rather than using the id in XPath, try expressing the XPath in terms of the DOM structure (tags):
//*/div/div/div/span/span/span/button[contains(text(),'Download')]
TIL you can validate your XPath by using the search function, rather than by running it in Selenium. I right-clicked the webpage, "inspect element", ctrl+f, and typed in the above XPath to validate that it is the Download button.
For posterity, if the above XPath is too specific, i.e. it is reliant on too many levels of the DOM structure, you can do something shorter, like
//*button[contains(text(),'Download')]
although, this may not be specific enough and may require an additional field, since there may be multiple buttons on the page with the 'Download' text.
Given the HTML you provided, you should be able to use
driver.find_element_by_id("yui-gen2-button")
I know you said you tried it but you didn't say if it works at all or what error message you are getting. If that never works, you likely have an IFRAME that you need to switch to.
If it works sometimes but not consistently due to changing ID, you can use something like
driver.find_element_by_xpath("//button[.='Download']")
On the code inspection view on Chrome you can right click on the item you want to find and copy the xpath. You can they find your element by xpath on Selenium.

Categories