I'm trying to make a bot that plays a card game automatically, but I'm facing the following problem.
I want the bot to just drop random cards I don't care about winning or losing and I'm using this code:
while True:
cards = driver.find_elements(by=By.CLASS_NAME, value="face-up")
for element in cards:
try:
actions = ActionChains(driver)
actions.move_to_element(element).click().perform()
break
except ElementNotInteractableException:
# If the element is not clickable, continue to the next one
print("couldn't click")
continue
I used this method so when it can't click it, it tries another card if it's droppable it drops it, but the problem is that when I run the bot sometimes it just drops perfectly and so fast without any problems then for no reason, it just can't click it anymore (starts printing couldn't click) until I click the card manually then it continues, I don't know what is the problem or how can I solve it so if anyone faced something like this before please tell me how to solve it and I tried to change the way I click the element (card) like using driver.execute_script("arguments[0].click();", element) or element.click() but still facing the same problem.
PS: while the bot is running and trying to click the cards and failing if I try to hover the mouse over the cards I can see the bot trying to hover over them but failing to click for some reason (even sometimes it clicks it when I manually hover over it, it rarely happens but maybe worth telling)
I think you may try:
wait for an element to be clickable (example from Java):
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(locator));
element.click();
Or wait for the whole page is loaded (Java example)
void waitForLoad(WebDriver driver) {
new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
Related
I am trying to automate a process to download data from a website. The code works if I run it step by step but if I run it all at once it fails. Giving the error
ElementNotInteractableException: Message: element not interactable
I have got around this using time.sleep(x amount of time) but it still seems to fail intermittently. I am having trouble implementing implicit waits. Any help would be appreciated. Code below.
import selenium
browser = webdriver.Chrome(executable_path=r'path\to\chromedriver.exe')
browser.get("https://map.sarig.sa.gov.au/")
browser.maximize_window()
browser.switch_to.frame(browser.find_element_by_id('MapViewer'))
browser.find_element_by_xpath('//*[#id="TourWidget"]/div[1]/span').click()
browser.find_element_by_xpath('//*[#id="menuAllMapLayers"]/div[2]/p').click()
browser.find_element_by_xpath('//*[#id="238"]/li[1]/div/div/span[1]').click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id="238"]/li[1]/div/div/span[1]').click()
browser.find_element_by_xpath('//*[#id="238"]/li[3]/div/div/label/span').click()
browser.find_element_by_xpath('//*[#id="239"]/li[1]/div/div/span[1]').click()
browser.find_element_by_xpath('//*[#id="239"]/li[3]/div/div/label/span').click()
browser.find_element_by_xpath('//*[#id="menuActiveLayers"]').click()
browser.find_element_by_xpath('//*[#id="groupOptions238"]/span').click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id="238"]/li[2]/div/div[3]/div[2]/span').click()
browser.find_element_by_xpath('//*[#id="groupOptions239"]/span').click()
time.sleep(3)
browser.find_element_by_xpath('//*[#id="239"]/li[2]/div/div[3]/div[2]/span').click()
Use ActionChains and get access to pause(3) instead of using sleep(3) but it could also help to use Waits and checking if your elements actually are "visible" rather than "present" (see expected_conditions)
It's a lot of dropdowns so maybe there are not visible all the time, but you can run these checks after doing a move_to_element() so it would actually be present.
I am a beginner in selenium and having a tough time understanding one of the errors appearing while using selenium chromedriver in python.
So, I am trying to click an element inside an svg tag by using css_selector. But I am getting ElementClickInterceptedException with the error (... is not clickable at point (1281, 60). Other element would receive the click:...). However, if I am putting time.sleep(5) before clicking the element, then I am able to click it. Why is it happening?
My first guess was maybe the element is not becoming visible or is inside an invisible box and I have to wait. Hence I tried to handle it with the explicit wait. But both cases timed out. So I assumed, it was not due to that. But then it is difficult for me to guess the reason, as time.sleep(5) is working.
Thank you in advance.
I have a website where I need to automate some actions. Every time a customer does a purchase, a div with an input and a submit button appears. On that div I need to enter a value and click submit. The div then closes until the next purchase appears in the same div. I need to do the same actions, and so on. It's indefinite.
I already found some solutions that point to the direction:
Selenium - wait until element is present, visible and interactable
WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".reply-button"))).click()
But I can't provide a specific time to wait. I need a solution that keeps going in a loop indefinitely and progress all purchases throughout the day
Every solution that I find solves the problem that the website takes time to load. But I have a completely different problem underlying. I need to wait for a purchases to happen. So I can't set a specific time to wait. It could be indefinite.
What Selenium function could help me -in a best practice way- with my problem?
You can use try and except
while true:
try:
WebDriverWait(browser, 30).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".reply-button"))).click()
except:
continue
else:
break
I use python/selenium for web-scraping and automation through Chrome. Recently I've come across a problem where some pages or websites would load endlessly as a means to prevent bots from scraping them (It often starts to happen after first time). I had no idea how to counter this until I came across the function in question:
wait = WebDriverWait(self.driver, 3)
element = wait.until(
EC.presence_of_element_located((By.XPATH, '//button[.="Sign up"]'))
)
The way I understood this function is that it sat a timeout for the page (3 seconds in this example) and at the same time checking whether an element has been loaded into the page or not. If the element has been loaded or if the wait times out, the program stops waiting for the page to load and continues on with the next line of code, which is, in my case, a print("timeout") function.
Thing is, as I use the function as demonstrated above the program still waits for the page to load, as "timeout" only appears in the console after I manually stop the page loading from the browser.
I am sure the element is present in the page (and quite visible) as it continues to load endlessly, because once I press the X button and stop the page loading, "timeout" is printed and the element is interacted with successfully.
I also tried EC.visibility_of_element_locatedto the same effect.
What is going wrong and how do I achieve the functionality I need?
Since you didn't share a link to the page you are working on I can only guess.
So my guess is: you are using a wrong locator.
Try using this
wait = WebDriverWait(self.driver, 3)
element = wait.until(EC.presence_of_element_located((By.XPATH, '//button[contains(.,"Sign up")]')))
Or this
wait = WebDriverWait(self.driver, 3)
element = wait.until(EC.presence_of_element_located((By.XPATH, '//button[contains(.,"sign up")]')))
I am writting bot using Selenium for a game where is a lot of clicking.
Sometimes it shows error Unable to locate element:
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: /html/body/div/div[1]/header/div/div[1]/a
I have correct Xpath but sometimes it gives me an error in different parts in my code. It is not that I have one mistake and it always show error in one place. My problem is that those errors are random. I am handling it like this:
try:
secondPhoto = self.driver.find_element_by_xpath(
'/html/body/span/section/main/article/div[2]/div/div[1]/div[1]')
secondPhotoOpen = ActionChains(self.driver)
secondPhotoOpen.move_to_element(secondPhoto)
secondPhotoOpen.click()
secondPhotoOpen.perform()
except:
time.sleep(3)
self.driver.find_element_by_xpath(
'/html/body/span/section/main/article/div[1]/div/div/div[1]/div[2]').click()
This is not a ideal solution. It still shows errors but less frequently.
I am also using time.sleep. Usually errors show up when I am doing something else on internet or I have lags(this is the reason why I am using time.sleep) Now, I have about 50 .click() in my code and for all clicks I am doing try except but still it is not working correctly.
Do you have an effective solution for this? How to write a code that use .click() to be 100% sure it works regardless lags, other
browser activity?
How to wait for full load of next page/image after click() ( I am
using time.sleep)?
You can use WebDriverWait:
btn = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "element_id")))
btn.click()
this will wait at least 10 seconds, until element will be clickable and only then clicks on it. Also I would recommend to read this. With WebDriverWait you don't have to have hard coded pauses.