I am getting trouble while shifting from the previous window to pop window and then pressing this press and hold button as we cannot able to get the id or class because it's dynamically changing. Is there any solution to get rid of this pop menu by long press and hold using selenium lib?
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//p[contains(.,'Press and Hold')]//preceding::input[1]")))
# element = driver.find_element_by_xpath("/html/body/div/div/div[2]/div[2]/p")
print("backing ot forward....")
action = ActionChains(driver)
action.click_and_hold(element)
action.perform()
time.sleep(10)
action.release(element)
action.perform()
time.sleep(0.2)
action.release(element)
```
Above are the lines of code that I am trying to run but due to dynamic id, it doesn't work well.
Here is something you may try. I had a similar issue. This worked for me.
The key is the release after 10 seconds (the timing might be different for your use case) and clicks again
element = driver.find_element_by_css_selector('#id-captcha') # captcha id
action = ActionChains(driver)
click = ActionChains(driver)
action.click_and_hold(element)
action.perform()
time.sleep(10) # change it as required
action.release(element)
action.perform()
time.sleep(0.2)
action.release(element)
Related
So I'm trying to learn about interacting with elements, after they are loaded (or enabled/interactable). In this case pressing button enables Edit box (after like 3-4secs), so you can write something. Here's link:
http://the-internet.herokuapp.com/dynamic_controls
Here is how it looks now - works, but what if this edit-box would load, for example, 6 seconds? Then it'd be wrecked up...
enable = browser.find_element(By.XPATH, "/html/body/div[2]/div/div[1]/form[2]/button")
enable.click()
time.sleep(5)
fillform = browser.find_element(By.XPATH, "/html/body/div[2]/div/div[1]/form[2]/input")
fillform.send_keys("testtt")
time.sleep(1)
I also tried browser.implicitly_wait(20) but it is like ignored and does nothing. Browser just keeps closing, because it can't find ENABLED edit box. It gives the error:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
I've tried another method for this - didn't work, as well...
element = WebDriverWait(browser, 5).until(EC.visibility_of_element_located((By.XPATH, "/html/body/div[2]/div/div[1]/form[2]/input")))
I am using Chrome+Python.
Use WebDriverWait() and wait for element_to_be_clickable(). Also use the following xpath option.
driver.get('http://the-internet.herokuapp.com/dynamic_controls')
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Enable']"))).click()
WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH, "//form[#id='input-example']//input"))).send_keys("testtt")
browser snapshot:
I am using selenium with chromedriver. I fill a form where there is a required field. Then I click the submit_and_stay button. Normally the click should send the info to the server and create an entry. This has a java-script. The click works but the required field disappears and the submit restarts. Other fields remain visible.
I have explicit wait,
I have scrolled to the button, I have hovered over it and I use EC.until it is clickable.
But still it fails to work. I used normal click, submit, key send return, then I used actions click and still it fails.
Here is the code:
html = driver.find_element_by_tag_name('html')
html.send_keys(Keys.END)
time.sleep(10)
id_box=driver.find_element_by_name("submitAddproductAndStay")
id_box=WebDriverWait(driver,
50).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#product-seo >
div:nth-child(8) > button:nth-child(3)')))
ActionChains(driver).move_to_element(id_box).perform()
driver.execute_script("arguments[0].scrollIntoView(true);", id_box);
time.sleep(5)
action = ActionChains(driver)
action.click(on_element = id_box).perform()
Any help?
After loosing 2 days on this, I figured out that the only way to go around this is to execute the click event by direct execute.javascript in the code:
driver.execute_script("arguments[0].click();", element)
As strange as it can be!!
I am doing browser automation and I am blocked at a certain point: at a moment, I ask the browser to click on a button, which in turn open up a new window. But sometimes the Internet is too slow, and so this new window takes time to load. I want to know how can I ask Selenium to wait until this new fresh window is fully loaded.
Here's my code:
driver.switch_to.default_content()
Button = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, 'addPicturesBtn')))
Button.click()
newWindow = driver.window_handles
time.sleep(5)
newNewWindow = newWindow[1]
driver.switch_to.window(newNewWindow)
newButtonToLoad = driver.find_element_by_id('d')
newButtonToLoad.send_keys('pic.jpg')
uploadButton = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.ID, 'uploadPics')))
uploadButton.click()
driver.switch_to.window(newWindow[0])
I get this error from time to time:
newNewWindow = newWindow[1]
IndexError: list index out of range
which make me think that a simple 'time.sleep(5)' doesn't do the work.
So, my question is, how can I wait until this new window is fully loaded before interacting with it?
thanks
You can try to use following code to wait until new window appears:
WebDriverWait(driver, 20).until(EC.number_of_windows_to_be(2))
Your code should looks like
Button.click()
WebDriverWait(driver, 20).until(EC.number_of_windows_to_be(2))
newWindow = driver.window_handles
newNewWindow = newWindow[1]
driver.switch_to.window(newNewWindow)
Considering #JimEvans comment, try below:
current = driver.window_handles[0]
Button.click()
WebDriverWait(driver, 20).until(EC.number_of_windows_to_be(2))
newWindow = [window for window in driver.window_handles if window != current][0]
driver.switch_to.window(newWindow)
What I'm using:
windows = set(driver.window_handles)
driver.execute_script("window.open()")
WebDriverWait(driver, 20).until(EC.new_window_is_opened(windows))
hwnd = list(set(driver.window_handles) - windows)[0]
You can create a function or a context manager like this answer for it if you find it necessary, but for essentially 3 lines (not counting the one that actually opens the window, which may be very different for each case), I prefer to just copy-paste.
To be thorough, here's a feature-enriched alternative:
#contextmanager
def wait_for_new_window(driver, timeout=10, switch=True):
"""Waits for a new window to open
Parameters:
driver: WebDriver.
Selenium WebDriver object.
timeout: int
Maximum waiting time
switch: bool
If `True` (default), switches to the window.
Exemplo:
>>> with wait_for_new_window(driver) as hwnds:
... driver.execute_script("window.open()");
... print("Window opened:", hwnds[0])
"""
windows = set(driver.window_handles)
handle = []
yield handle
WebDriverWait(driver, timeout).until(EC.new_window_is_opened(windows))
hwnds = list(set(driver.window_handles) - windows)
handle.extend(hwnds)
if switch:
driver.switch_to.window(hwnds[0])
The exact answer for waiting a NEW window to be fully loaded is:
using url_changes from expected_conditions with the old URL parameter as "about:blank" :
WebDriverWait(Driver, 15).until(EC.url_changes("about:blank"))
A sample code might look like:
...
# Wait till a new window opened (2nd window in this example)
WebDriverWait(Driver, 15).until(EC.number_of_windows_to_be(2))
# Switch to second window
window_after = Driver.window_handles[1]
Driver.switch_to.window(window_after)
# Wait till **new window fully loaded**:
WebDriverWait(Driver, 15).until(EC.url_changes("about:blank"))
...
I want a WebDriver instance to monitor a page indefinitely until an input box appears with the name 'move.' Once the input box appears, I want to fill it with some text and click a submit button adjacent to the form. What is the easiest way to do this?
I have something like this now:
try:
move = WebDriverWait(driver, 1000).until(
EC.presence_of_element_located((By.NAME, "move"))
)
finally:
wd.quit()
And the button adjacent to the form has no name or id, so I am locating it by XPATH. I want to wait until that form is present before click the button.
How do I do this?
monitor a page indefinitely until an input box appears
An Explicit wait you've used in the example requires a timeout value defined. Either you set a very high value for the timeout, or it is not an option.
Alternatively, you can have a while True loop until an element would be found:
from selenium.common.exceptions import NoSuchElementException
while True:
try:
form = driver.find_element_by_name("move")
break
except NoSuchElementException:
continue
button = form.find_element_by_xpath("following-sibling::button")
button.click()
where I'm assuming the button element is a following sibling of the form.
I would like to write a code that would make Python scrape some data on a page, then click on the "next" button at the bottom of the page, scrape some data on the second page, click on the "next" button, etc. until the last page, where clicking on "Next" is no longer possible (because there is no "next").
I would like to make the code as general as possible and not specify beforehand the number of clicks to be done.
Following this question (How can I make Selenium click through a variable number of "next" buttons?), I have the code below. Python does not report any error, but the program stops after the first iteration (after the first click on the "next").
What am I missing here? Many thanks!
driver = webdriver.Firefox()
driver.get("http://www.mywebsite_example.com")
try:
wait = WebDriverWait(driver, 100)
wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'reviews_pagination_link_nav')))
driver.find_element_by_class_name("reviews_pagination_link_nav").click()
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'reviews_pagination_link_nav')))
while EC.element_to_be_clickable((By.CLASS_NAME,'reviews_pagination_link_nav')):
driver.find_element_by_class_name("reviews_pagination_link_nav").click()
if not driver.find_element_by_class_name("reviews_pagination_link_nav"):
break
wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'reviews_pagination_link_nav')))
finally:
driver.quit()
I would make an endless while True loop and break it once there is TimeoutException thrown - this would mean there are no pages to go left:
wait = WebDriverWait(driver, 10)
while True:
# grab the data
# click next link
try:
element = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'reviews_pagination_link_nav')))
element.click()
except TimeoutException:
break
For this to work, you need to make sure that once you hit the last page, the element with class="reviews_pagination_link_nav" is not on the page or is not clickable.