For loop Selenium - Incomplete Task

Viewed 265

I am performing an automation bot, capable of sharing post. However, when it comes to performing the task more than 3 times, I get an error and program stops working. I am not sure why my code is able to perform the task 3 times and then stops.

Here is my code:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as ECDS
import time


driver = webdriver.Chrome()
driver.get("https://www.poshmark.com") #Open webpage
Log_Field=(By.XPATH, "//a[contains(text(),'Log in')]")
Email= (By.XPATH, "//input[@placeholder='Username or Email']")
Pass= (By.XPATH, "//input[@placeholder='Password']")
Second_Log= (By.XPATH, "//button[@class='btn btn--primary']")
SF = (By.XPATH, "//img[@class='user-image user-image--s']")
MyCloset = (By.XPATH, "//a[contains(text(),'My Closet')]")


WebDriverWait(driver, 20).until(EC.element_to_be_clickable(Log_Field)).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable(Email)).send_keys("xx@xx.com")
driver.find_element_by_xpath("//input[@placeholder='Password']").send_keys("xxx")
driver.find_element_by_xpath("//button[@class='btn blue btn-primary']").click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable(SF)).click()
WebDriverWait(driver, 20).until(EC.element_to_be_clickable(MyCloset)).click()

for i in range(100):
    driver.find_element_by_tag_name('body').send_keys(Keys.END)#Use send_keys(Keys.HOME)
    driver.find_element_by_xpath("//div[6]//div[1]//div[2]//div[3]//i[1]").click()
    driver.find_element_by_xpath("//div[@class='share-wrapper-container']").click()
    driver.refresh()
time.sleep(20)

The error that I am getting is the following:

  Traceback (most recent call last):
  File "/home/pi/Documents/Bot_Poshmark.py", line 27, in <module>
    driver.find_element_by_xpath("//div[6]//div[1]//div[2]//div[3]//i[1]").click()
  File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/webelement.py", line 80, in click
    self._execute(Command.CLICK_ELEMENT)
  File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.7/dist-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <i class="icon share-gray-large"></i> is not clickable at point (870, 163). Other element would receive the click: <div class="tile col-x12 col-l6 col-s8 p--2">...</div>
  (Session info: chrome=78.0.3904.108)

Any ideas why my code is only working not more than 3 times? Thank you

1 Answers

I had the same problem several times while testing my selenium web automation. As the exception tells, this object is not clickable. That means you have to dive deeper into the HTML tree to find an element that is always clickable. If you hover over the HTML-lines Chrome shows you the according piece of website. However, if this is not possible, try to let your code sleep() for a bit :-) You could do that for a certain amount of time

Or you use WebDriverWait() as in the comments described: WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "your XPATH"))).click() (You missed one (), this should remove your error: Without: Argument 1 = self [Keep that in mind with Python!!], Argument 2 = By.XPATH and 3 = "the xpath". With the (), Argument 2 and 3 are together)

WebDriverWait() requires a timeout parameter because selenium does not know whether the element exists or not. But you could easily create your own waiting-method. Pay attention: you have to know that the element exists or you will end up with an infinite loop.

Here's the code:

from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

def wait_for(driver, method):
    """Calls the method provided with the driver"""
    while True:
        try:
            element = method(driver)
            if element:
                return element
        except:
            pass
        sleep(0.5)

It tries to find the element and when it's found, it returns it. You can use it like so:

el = wait_for(driver, EC.element_to_be_clickable((By.XPATH,  "//input[@class='13e44'")))
el.click()

Disclaimer: This code is not fully my creation. I adapted the selenium source-code so it fits our needs :)

Related