I'm trying to use ActionChains to click a button with
python but it just refuses to work no matter what I do.
The issue is that whenever the website opens, it opens with an overlay.
I want my program to click the 'OK' button on the overlay. Whatever code I write just ends up clicking the overlay itself.
Here is my code:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
URL = 'https://sam.gov/search/?index=opp&page=1&sort=-relevance&sfm%5Bstatus%5D%5Bis_active%5D=true&sfm%5Bdates%5D%5BresponseDue%5D%5BresponseDueSelect%5D=customDate&sfm%5Bdates%5D%5BresponseDue%5D%5BresponseDueFrom%5D=05%2F29%2F2021&sfm%5Bdates%5D%5BresponseDue%5D%5BresponseDueTo%5D=05%2F29%2F2022&sfm%5Bkeywords%5D%5B0%5D%5Bkey%5D=541511&sfm%5Bkeywords%5D%5B0%5D%5Bvalue%5D=541511'
driver.get(URL)
overlay = driver.find_element(By.ID, "cdk-overlay-0")
button = driver.find_element(By.CSS_SELECTOR, "button.usa-button")
ActionChains(driver).move_to_element(overlay).click(button).perform()
And the relevant HTML from the webpage I'm looking at is:
<div id="cdk-overlay-0" class="cdk-overlay-pane" ...>
for the overlay, and
<button class="usa-button">OK</button>
for the button itself.
My code always ends up clicking just on the overlay and not the button. It ends up looking like this (the overlay gets a blue outline when clicked):
Yo, try this
from selenium import webdriver
URL = 'https://sam.gov/search/?index=opp&page=1&sort=-relevance&sfm%5Bstatus%5D%5Bis_active%5D=true&sfm%5Bdates%5D%5BresponseDue%5D%5BresponseDueSelect%5D=customDate&sfm%5Bdates%5D%5BresponseDue%5D%5BresponseDueFrom%5D=05%2F29%2F2021&sfm%5Bdates%5D%5BresponseDue%5D%5BresponseDueTo%5D=05%2F29%2F2022&sfm%5Bkeywords%5D%5B0%5D%5Bkey%5D=541511&sfm%5Bkeywords%5D%5B0%5D%5Bvalue%5D=541511'
driver = webdriver.Chrome()
driver.get(URL)
driver.find_element_by_xpath(r'/html/body/div/div[2]/div/sds-dialog-container/layout-splash-modal/div[4]/div[2]/div/button').click()
I just used the xpath and clicked it without actionchains
Related
I am trying to automate downloads from a webpage using selenium.
So far my strategy is to instantiate a firefox driver that loads the page and clicks the download button. However, to be clickable, the button needs to be visible, i.e. not covered by any banners on the page (at least in my understanding). Therefore I need to scroll down (I use scrollIntoView()). If I run button.click() immediately after scrolling down, the download doesn't start, if I hard code a sufficient timeout in between it works out fine. Can somebody help me to set a timeout conditioned on the scroll down?
Here is my code:
from selenium import webdriver
profilePath = '/path/to/my/firefox/profile'
profile = webdriver.FirefoxProfile(profilePath)
driver = webdriver.Firefox(firefox_profile=profile)
driver.get("https://www.happyscribe.com/public/lex-fridman-podcast-artificial-intelligence-ai/164-andrew-huberman-sleep-dreams-creativity-the-limits-of-the-human-mind")
button = driver.find_element_by_id('btn-download')
target=driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)
time.sleep(10)
button.click()
and this is the html code of the button:
<button class="hs-btn-secondary small" id="btn-download" type="button">Download</button>
I would be very thankful for any direct help or suggestions on how to tackle the problem from a different angle.
It sounds like you may need to induce WebDriverWait for the element to by clickable. You could do so like this. It will wait for the element to be both visible and enabled before clicking.
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
profilePath = '/path/to/my/firefox/profile'
profile = webdriver.FirefoxProfile(profilePath)
driver = webdriver.Firefox(firefox_profile=profile)
driver.get("https://www.happyscribe.com/public/lex-fridman-podcast-artificial-intelligence-ai/164-andrew-huberman-sleep-dreams-creativity-the-limits-of-the-human-mind")
button = driver.find_element_by_id('btn-download')
target=driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", button)
WebDriverWait(driver, 10).until(EC.element_to_be_clickable(button))
button.click()
Webpage View
Webpage HTML Snippet
Problem
I'm trying to use Python and Selenium to scrape this web site where the submenu shows after the mouse goes over the "Dossiê" menu.
Attempt
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
browser = webdriver.Chrome()
action = ActionChains(browser)
(...)
action.move_to_element(browser.find_element_by_id('menuItem1')).perform()
When this code is run, a NoSuchElementException is raised. The element is found, but the move_to_element call doesn't show the submenu.
I have tried to make my script click the Purchase/Buy Family button on the Spotify Checkout Page. No matter what class, CSS, XPath, ID, or whatever I put in, it's just saying it could not find the object.
This is the button. It's not in an iframe:
<div class="sc-fzXfOu cvoJMt">
<button id="checkout_submit" class="Button-oyfj48-0 kaOWUo sc-fzXfOv tSdMK">
Buy Premium Family
</button>
</div>
My code:
time.sleep(3)
buy = driver.find_element_by_xpath("/html/body/div[3]/div/div/div/div/div/div/div[3]/div/div/div[2]/form/div[2]/button").click()
I am able to click the button,by a different xpath
driver.findElement(By.xpath("//button[#id='checkout_submit']")).click();
Edit -
Your xpath also works for me only when i load the page initially and there is no change in the dom - /html/body/div[3]/div/div/div/div/div/div/div[3]/div/div/div[2]/form/div[2]/button
It doesn't work when some new event or error is displayed and the dom structure changes.
Why use such relative XPath when the element has distinguishable attributes?
The problem here is the form is not static you have to wait loading of all elements.
And page loads with pane to accept cookies who can mask elements you want to run action on.
The best way in that case is first accept cookies and then run all actions you need.
Try to adapt this code for your needs, that run with success on my test.
In case you run this code you have to brake execution to login first, when the driver get the page.
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.remote.webelement import WebElement
# change this line
path_driver = "your_path_to_chrome_driver"
by, buy_selector, cookies_selector = By.CSS_SELECTOR, 'button#checkout_submit', "button#onetrust-accept-btn-handler"
driver = webdriver.Chrome(path_driver)
driver.maximize_window()
actions = ActionChains(driver)
driver.get("https://www.spotify.com/us/purchase/offer/premium-family/?country=US")
# wait for loading buy button
sls = wait.until(EC.presence_of_all_elements_located((by, buy_selector)))
if sls:
# get accept cookies button element and click
cookies_accept = driver.find_element_by_css_selector(cookies_selector)
if isinstance(cookies_accept, WebElement):
cookies_accept.click()
# get buy button element, move to element and click
buy = driver.find_element_by_css_selector(buy_selector)
if isinstance(buy, WebElement) and buy.is_displayed() and buy.is_enabled():
actions.move_to_element(buy).click(buy).perform()
After handling a pop up overlay the rest of the code no longer works.
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('https://www.vapordna.com/login.asp')
#handling popup
browser.find_element_by_css_selector("div.age-verify-button.age-modal__btn.btn.btn-primary").click()
browser.find_element_by_link_text("Yes").click()
If I don't close the pop up the rest of the code works, if I close the popup none of the code after that point works.
emailElem = browser.find_element_by_name("email")
emailElem.send_keys("****#****.com")
passwordElem = browser.find_element_by_name("password")
passwordElem.send_keys("******")
passwordElem.submit()
I have tried adding this line but it doesn't help,
browser.switchTo().defaultContent();
To my understanding the popup isn't in a new iframe or window so I'm not sure why there would be any problem with continuing to interact with the page.
I also tried clicking on the body before continuing
browser.find_element_by_tag_name("body").click()
After seeing your website I observe this is neither an frame nor a window, I just a form so there is no need to use here browser.switchTo().defaultContent(); which actually using for switching from any frame to default, Actually when you are going to find this button on the opened popup which overlay all the page, It would not be full loaded on the page, so you should try using WebDriverWait to wait until this button visible on the page.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Firefox()
browser.get('https://www.vapordna.com/login.asp')
wait = WebDriverWait(driver, 10)
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.age-verify-button.age-modal__btn.btn.btn-primary"))).click()
Now after clicking on this agreement button you can proceed further steps for login.
I am trying to click an element, for example "AH", in this page. I use the following code.
from selenium import webdriver
url = "http://www.oddsportal.com/soccer/brazil/serie-a/internacional-santos-vcGTTAKH/"
driver = webdriver.Firefox()
driver.get(url)
element_to_click = driver.find_element_by_link_text("AH")
element_to_click.click()
The problem is that after the element is clicked and the new page is loaded, it goes back to the first page.
Focus the element and call click_and_hold action (worked for me):
from selenium.webdriver import ActionChains
actions = ActionChains(driver)
actions.move_to_element(element_to_click).click_and_hold(element_to_click).perform()
alecxe , that works.
Just to add to the discussion here
So on mouse down it is invoking onClick for the uid(4), when we do a normal click on the element we do not realize that it worked on mouse down not on mouse click.
Thats why when we are using webdriver to do element.click() on it, this does not work and when we use Actions class to simulate mouse down using click_and_hold, It works !!