Reputation: 23
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
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
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
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