iWYO
iWYO

Reputation: 23

Python selenium: How to click on span element?

So hello! First of all. I'm not very familiar with python and selenium that's why i need your help! The story: I want to make an IMVU auto badge collector for my gf which means you type a url that you want to collect badges from then it will automatically collects for you. (To collect badges you have to click a span) I writed the beggining of the code so i can login automatically and start to collect BUT some weird things are happening. When i'm not login the program can click on the spans but when i login it can't. Why? The id and the class is the same. I tried lot of thing: i changed the find_element to xpath, when i login i tried to make a new window then collect there etc. but nothing happened. Can somebody help me? I would be very happy!

here is the code:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
from selenium.webdriver.common.keys import Keys


PATH = "C:\chromedriver\chromedriver.exe"
options = Options()
options.headless = False
options.add_argument("--mute-audio")
driver = webdriver.Chrome(PATH, options=options)

def login():
    driver.get("https://secure.imvu.com/welcome/login/")

    time.sleep(3)

    driver.find_element_by_xpath('/html/body/section/div/div/div/section/div/div/button').click()
    driver.find_element_by_xpath('//*[@id="__default__"]/div[1]/div[2]/div/div[2]/div/ul/a').click() 

    time.sleep(3)

    username = driver.find_element_by_xpath('/html/body/div[6]/section[2]/div/div/div/section/form/div[1]/input')
    password = driver.find_element_by_xpath('/html/body/div[6]/section[2]/div/div/div/section/form/div[2]/div[2]/input')
    username.send_keys("username")
    password.send_keys("password")

    time.sleep(3)

    driver.find_element_by_xpath('/html/body/div[6]/section[2]/div/div/div/section/form/div[4]/button').click()

    time.sleep(5)

def claim():
    #driver.get("https://secure.imvu.com/welcome/login/")

    #input("Press Enter to continue...")

    #driver.execute_script('''window.open("https://avatars.imvu.com/qub","_blank");''')

    #time.sleep(3)

    driver.get("https://avatars.imvu.com/qub")

    time.sleep(5)

    driver.find_element_by_xpath("//span[contains(@id,'grant-badge-74354585-1')]").click()

    time.sleep(5)


    #driver.find_element_by_xpath('/html/body/table[1]/tbody/tr/td/table[2]/tbody/tr/td[1]/div/div[4]/table/tbody/tr/td/div/div/table/tbody/tr[1]/td[1]/span').click()


login()
claim()

Upvotes: 2

Views: 421

Answers (3)

StyleZ
StyleZ

Reputation: 1273

The cruisepandey's answer would normally work, but unfortunately, in this case, it will not work. The reason why is that if you look into the HTML, you will see that those badges are in iframe ... which means you need to switch to this iframe and navigate it there. In this case, all you need to do is switch to the iframe and find a new path to your elements using the iframe website for navigation.

Here is an example code, how you can do it :)

def claim():

    driver.get("https://avatars.imvu.com/qub")

    time.sleep(5)

    iframe = driver.find_element_by_xpath('//*[@id="avatar_content"]')
    driver.switch_to.frame(iframe)

    driver.find_element_by_xpath("//span[contains(@id,'grant-badge-74354585-1')]").click()

    # switch back
    driver.switch_to.default_content()

    time.sleep(5)

code taken from -> Switch to an iframe through Selenium and python

GL HF ;)

Upvotes: 1

iWYO
iWYO

Reputation: 23

Thank you for the answer. I copied your xpath code but the problem is the same. When i remove the login function it works because the program is not logging in but when i want to use it the claim function is not working.

The error that i'm getting:

File "d:\Programming\Python\IMVU badge colletor\collect.py", line 65, in <module>
    claim()
  File "d:\Programming\Python\IMVU badge colletor\collect.py", line 54, in claim
    wait.until(EC.element_to_be_clickable((By.XPATH, "//span[starts-with(@id,'grant-badge')]"))).click()
  File "C:\Users\iWYO\AppData\Local\Programs\Python\Python310\lib\site-packages\selenium\webdriver\support\wait.py", line 89, in until
    raise TimeoutException(message, screen, stacktrace)
selenium.common.exceptions.TimeoutException: Message:
Stacktrace:
Backtrace:
        Ordinal0 [0x00923AB3+2505395]
        Ordinal0 [0x008BAE41+2076225]
        Ordinal0 [0x007C2498+1057944]
        Ordinal0 [0x007ECB74+1231732]
        Ordinal0 [0x00816D92+1404306]
        Ordinal0 [0x00805A2A+1333802]
        Ordinal0 [0x00815168+1397096]
        Ordinal0 [0x008058BB+1333435]
        Ordinal0 [0x007E23E4+1188836]
        Ordinal0 [0x007E323F+1192511]
        GetHandleVerifier [0x00AACB36+1554566]
        GetHandleVerifier [0x00B54A0C+2242396]
        GetHandleVerifier [0x009B0E0B+523099]
        GetHandleVerifier [0x009AFEB0+519168]
        Ordinal0 [0x008C02FD+2097917]
        Ordinal0 [0x008C4388+2114440]
        Ordinal0 [0x008C44C2+2114754]
        Ordinal0 [0x008CE041+2154561]
        BaseThreadInitThunk [0x7670FA29+25]
        RtlGetAppContainerNamedObjectPath [0x76F27A9E+286]
        RtlGetAppContainerNamedObjectPath [0x76F27A6E+238]

Upvotes: 0

cruisepandey
cruisepandey

Reputation: 29362

You are using absolute xpath which is brittle.

You should opt for relative xpath.

The below code is just for login, Where I am using explicit waits.

driver = webdriver.Chrome(driver_path)
driver.maximize_window()
wait = WebDriverWait(driver, 30)

driver.get("https://secure.imvu.com/welcome/login/")
wait.until(EC.element_to_be_clickable((By.LINK_TEXT, "Log In"))).click()
wait.until(EC.visibility_of_element_located((By.NAME, "avatarname"))).send_keys('username')
wait.until(EC.visibility_of_element_located((By.NAME, "password"))).send_keys('password')
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.label-log-in button"))).click()

Imports :

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

Now coming to the actual problem:

the xpath that you've been using contains some number dynamic values, Please use the below xpath.

driver.get("https://avatars.imvu.com/qub")
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[starts-with(@id,'grant-badge')]"))).click()

Upvotes: 0

Related Questions