pythonselenium-webdriverweb-scraping

Python script to extract data post login from a website in chrome


i am writing a Python script to extract data from valueresearchonline.com using my login credentials. I am using Selenium webdriver as my website will have dynamic data that i would like to scrape. however i am unable to click on the button that says "login with password", i have pasted a screenshot of the login page.

website screenshot

This is the html code for the button i am trying to access.

<button class="login-button pswd has-shadow-animation new-login-btn" data-user="Log in with password"> Log in with password </button>.

The button doesn't have an ID or name, so the code below doesn't work.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import pandas as pd
import requests
from bs4 import BeautifulSoup

driver = webdriver.Chrome()
url = "https://www.valueresearchonline.com/login/?site-code=VROL&amp;target=%2F&amp;utm_source=home&amp;utm_medium=vro&amp;utm_campaign=desktop-profile-menu/"
driver.get(url)
driver.implicitly_wait(5)  # Wait for 5 seconds
element = driver.find_element(By.NAME, 'login-button pswd has-shadow-animation new-login-btn')
print(element.text)

The error message is pasted below

---------------------------------------------------------------------------
NoSuchElementException                    Traceback (most recent call last)
Cell In[5], line 2
      1 # Find an element by its ID
----> 2 element = driver.find_element(By.NAME, 'login-button pswd has-shadow-animation new-login-btn')
      3 print(element.text)

File ~\anaconda3\Lib\site-packages\selenium\webdriver\remote\webdriver.py:770, in WebDriver.find_element(self, by, value)
    767         raise NoSuchElementException(f"Cannot locate relative element with: {by.root}")
    768     return elements[0]
--> 770 return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]

File ~\anaconda3\Lib\site-packages\selenium\webdriver\remote\webdriver.py:384, in WebDriver.execute(self, driver_command, params)
    382 response = self.command_executor.execute(driver_command, params)
    383 if response:
--> 384     self.error_handler.check_response(response)
    385     response["value"] = self._unwrap_value(response.get("value", None))
    386     return response

File ~\anaconda3\Lib\site-packages\selenium\webdriver\remote\errorhandler.py:232, in ErrorHandler.check_response(self, response)
    230         alert_text = value["alert"].get("text")
    231     raise exception_class(message, screen, stacktrace, alert_text)  # type: ignore[call-arg]  # mypy is not smart enough here
--> 232 raise exception_class(message, screen, stacktrace)

NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[name="login-button pswd has-shadow-animation new-login-btn"]"}
  (Session info: chrome=131.0.6778.205); For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#no-such-element-exception

thanks for the help.


Solution

  • The problem is your locator. You've used By.Name() but that BUTTON has no name. See name for more info.

    <button class="login-button pswd has-shadow-animation new-login-btn" data-user="Log in with password">Log in with password</button>
    

    What you have put as NAME are actually the classes applied to that element. You can't use By.CLASS_NAME() here either because it expects only a single class and that is 4 classes. You could use a CSS selector, button.pswd or another unique attribute on that element is data-user, data-user="Log in with password". Either will work... I would probably lean towards the data-user attribute because it's a custom attribute put there by the devs and is probably less likely to change. You will need a wait in this case.

    wait = WebDriverWait(driver, 10)
    wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-user='Log in with password']"))).click()