Search code examples
pythonseleniumxpathcss-selectorswebdriverwait

Error locating div aria label with xpath Selenium


So I'm trying to find a way to make sure my bot doesn't get confused and click on the Following button again (it uses span to detect text) when it has already followed that particular user. I am trying to detect that if a user is already followed, the bot should skip him through another method, which is if the bot finds the following text on the user's profile "Turn on Tweet notifications" that means the user is already followed because there will be a bell icon/button present on his profile.

The issue is, I fail to detect that text/button. What am I doing wrong?

Here's the code:

def to_follow_delay():
    def to_follow_delay_2():
        try:
            driver.get(next(urls))
            if wait.until(EC.visibility_of_element_located((By.XPATH, "//div[contains(@aria-label,'Turn on Tweet notifications')]"))):
                i = 1
                while True:
                    skipped_user = "skipped_following" + str(i) + ".png"
                    if not os.path.isfile(skipped_user):
                        break
                    i += 1

                already_following = datetime.datetime.now()
                print(already_following, "Already following... skipping")
                driver.get_screenshot_as_file(skipped_user)

                def skip_user():
                    driver.get(next(urls))
            
                skiptimer = threading.Timer(10, skip_user)
                skiptimer.start
                return to_follow_delay()
            else:
                def follow_user():
                    sleep(5)
                
                    followuser = wait.until(EC.element_to_be_clickable((By.XPATH, '//span[text()="Follow"]')))
                    followuser.click()
                
                    followsuccess = datetime.datetime.now()
                    print(followsuccess, "Follow successful")

                    print("--- %s seconds ---" % (time.time() - starting4))

                    i = 1
                    while True:
                        followed_user_success = "followed" + str(i) + ".png"
                        if not os.path.isfile(followed_user_success):
                            break
                        i += 1
                        
                    driver.get_screenshot_as_file(followed_user_success)

                    followedper_runcounter.set(followedper_runcounter.get() + 1)
                    followedcounter.set(followedcounter.get() + 1)
                    return operation_follow()

                timer4 = threading.Timer(tofollowdelayvalue_txt.get(), follow_user)
                timer4.start()
                starting4 = time.time()

        except StopIteration:
            nourls = datetime.datetime.now()
            print(nourls, "No more urls.")
            return

    timer5 = threading.Timer(5, to_follow_delay_2)
    timer5.start()

Twitter code:

<div aria-label="Turn on Tweet notifications" role="button" tabindex="0" class="css-18t94o4 css-1dbjc4n r-1niwhzg r-1ets6dv r-sdzlij r-1phboty r-rs99b7 r-6gpygo r-1kb76zh r-2yi16 r-1qi8awa r-1ny4l3l r-o7ynqc r-6416eg r-lrvibr"><div dir="auto" class="css-901oao r-1awozwy r-18jsvk2 r-6koalj r-18u37iz r-16y2uox r-37j5jr r-a023e6 r-b88u0q r-1777fci r-rjixqe r-bcqeeo r-q4m81j r-qvutc0"><svg viewBox="0 0 24 24" aria-hidden="true" class="r-18jsvk2 r-4qtqp9 r-yyyyoo r-z80fyv r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-19wmn03"><g><path d="M23.24 3.26h-2.425V.832c0-.414-.336-.75-.75-.75s-.75.336-.75.75V3.26H16.89c-.414 0-.75.335-.75.75s.336.75.75.75h2.426v2.424c0 .414.336.75.75.75s.75-.336.75-.75V4.76h2.425c.415 0 .75-.337.75-.75s-.336-.75-.75-.75zm-6.23 7.606c.02-2.434-.782-4.597-2.258-6.09-1.324-1.342-3.116-2.084-5.046-2.093h-.013c-1.93.01-3.722.75-5.046 2.092C3.172 6.27 2.37 8.433 2.39 10.867 2.426 15 .467 16.56.39 16.62c-.26.193-.367.53-.266.838.102.308.39.515.712.515h4.716c.11 2.226 1.94 4.007 4.194 4.007s4.083-1.78 4.194-4.007h4.625c.32 0 .604-.206.707-.51s0-.643-.255-.838c-.082-.064-2.043-1.625-2.008-5.76zM9.745 20.48c-1.426 0-2.586-1.11-2.694-2.508h5.388c-.108 1.4-1.268 2.507-2.694 2.507zm-7.29-4.007c.702-1.095 1.457-2.904 1.434-5.618-.017-2.062.614-3.8 1.825-5.025C6.757 4.774 8.172 4.19 9.7 4.184c1.527.007 2.943.59 3.985 1.646 1.21 1.226 1.84 2.963 1.823 5.025-.022 2.714.732 4.523 1.437 5.618H2.455z"></path></g></svg><span class="css-901oao css-16my406 css-bfa6kz r-poiln3 r-a023e6 r-rjixqe r-bcqeeo r-qvutc0"></span></div></div>

The error stacktrace:

    if wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "button[aria-label='Turn on Tweet notifications'][role='button']"))):
  File "C:\Users\Cassano\AppData\Roaming\Python\Python38\site-packages\selenium\webdriver\support\wait.py", line 89, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Stacktrace:
Backtrace:
        Ordinal0 [0x00AF6903+2517251]
        Ordinal0 [0x00A8F8E1+2095329]
        Ordinal0 [0x00992848+1058888]
        Ordinal0 [0x009BD448+1233992]
        Ordinal0 [0x009BD63B+1234491]
        Ordinal0 [0x009E7812+1406994]
        Ordinal0 [0x009D650A+1336586]
        Ordinal0 [0x009E5BBF+1399743]
        Ordinal0 [0x009D639B+1336219]
        Ordinal0 [0x009B27A7+1189799]
        Ordinal0 [0x009B3609+1193481]
        GetHandleVerifier [0x00C85904+1577972]
        GetHandleVerifier [0x00D30B97+2279047]
        GetHandleVerifier [0x00B86D09+534521]
        GetHandleVerifier [0x00B85DB9+530601]
        Ordinal0 [0x00A94FF9+2117625]
        Ordinal0 [0x00A998A8+2136232]
        Ordinal0 [0x00A999E2+2136546]
        Ordinal0 [0x00AA3541+2176321]
        BaseThreadInitThunk [0x770EFA29+25]
        RtlGetAppContainerNamedObjectPath [0x77B47A9E+286]
        RtlGetAppContainerNamedObjectPath [0x77B47A6E+238]

Solution

  • To locate the visible element with text as Turn on Tweet notifications you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:

    • Using CSS_SELECTOR:

      element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div[aria-label='Turn on Tweet notifications'][role='button']")))
      
    • Using XPATH:

      element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[@aria-label='Turn on Tweet notifications' and @role='button']")))
      
    • Note : You have to add the following imports :

      from selenium.webdriver.support.ui import WebDriverWait
      from selenium.webdriver.common.by import By
      from selenium.webdriver.support import expected_conditions as EC