How to correctly find elements by class name on Python? Selenium related

I'm trying to automate a process on this page, and according to its html code, after clicking the wallet button located at the top right corner of that page, it deploys 4 main wallets to choose to log in to the page.

preview1

All of those wallets share the same class which is elements__StyledListItem-sc-197zmwo-0 QbTKh, and I wrote the code below in order to try to get their button names (Metamask, Coinbase wallet...), here:

driver = webdriver.Chrome(service=s, options=opt) #execute the chromedriver.exe with the previous conditions
driver.implicitly_wait(10)
driver.get('https://opensea.io/') #go to the opensea main page.
WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="__next"]/div/div[1]/nav/ul/div[2]/li/button'))) #wait for the wallet button to be enabled for clicking
wallet_button = driver.find_element(By.XPATH, '//*[@id="__next"]/div/div[1]/nav/ul/div[2]/li/button') 
wallet_button.click() #click that wallet button
wallet_providers = driver.find_elements(By.CLASS_NAME, "elements__StyledListItem-sc-197zmwo-0 QbTKh") #get the list of wallet providers
for i in wallet_providers:
    print(i)

After compiling the code above, I noticed that it didn't print anything, and it was due to the empty array of wallet_providers, which is very weird because I understand that by calling find_elements(By.CLASS_NAME, "the_class_name") it will then return an array containing the elements that share the same class, but it didn't do that in this case.

So, I would appreciate if someone could explain me what did I do wrong? In the end, I just wanted to manage to click on the Metamask button which doesn't always stay at the same location, sometimes it's the first element of that list, sometimes the second...


Solution 1:

You are using this CLASS_NAME elements__StyledListItem-sc-197zmwo-0 QbTKh which has space in it.

In Selenium, a class name having space will not be parsed and will throw the error.

The reason why you did not get the error is cause you are using find_elements that will either return a list of web element or nothing.

So how to resolve this?

remove the space and put a . instead to make a CSS_SELECTOR

try this:

wallet_providers = driver.find_elements(By.CSS_SELECTOR, ".elements__StyledListItem-sc-197zmwo-0.QbTKh") #get the list of wallet providers

to be honest we can have better locator than this, cause it seems these values 197zmwo-0.QbTKh are generated dynamically.

I would rather use this CSS:

li[class^='elements__StyledListItem'] span[font-weight]

or this xpath:

//li[starts-with(@class,'elements__StyledListItem')]//descendant::span[@font-weight]

Also, you should print it like this: (this is one way but there are others as well):

Code:

driver.get("https://opensea.io/")

WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="__next"]/div/div[1]/nav/ul/div[2]/li/button'))) #wait for the wallet button to be enabled for clicking
wallet_button = driver.find_element(By.XPATH, '//*[@id="__next"]/div/div[1]/nav/ul/div[2]/li/button')
wallet_button.click() #click that wallet button
wallet_providers = driver.find_elements(By.CSS_SELECTOR, "li[class^='elements__StyledListItem'] span[font-weight]") #get the list of wallet providers
for i in wallet_providers:
    print(i.get_attribute('innerText'))

Console output:

WalletConnect
MetaMask
Coinbase Wallet
Fortmatic

Process finished with exit code 0

Solution 2:

The locators you are using are not relative enough, and on my first inspection, I somehow didn't locate them in the DOM. So, refactored code with relative locators to make the code work.

   driver.get('https://opensea.io/') #go to the opensea main page.
    WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//*[@title='Wallet']"))).click()
    wallets = WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.XPATH, "//*[@data-testid='WalletSidebar--body']//li")))
    for wallet in wallets:
        print(wallet.text)

Output:

WalletConnect
MetaMask
Popular
Coinbase Wallet
Fortmatic

Process finished with exit code 0