3

I am trying to automate process of sign up on virus total site and for this using selenium in python. But having a problem while getting element by id. i am stuck in this any help will be appreciated thanks. here is my code i am trying.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
driver =webdriver.Chrome()
driver.get('https://www.virustotal.com/gui/join-us')
print(driver.title)
search = driver.find_element_by_id("first_name")
search.send_keys("Muhammad Aamir")
search.send_keys(Keys.RETURN)
time.sleep(5)
driver.quit()
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352

2 Answers2

3

The First name field within the website https://www.virustotal.com/gui/join-us is located deep within multiple #shadow-root (open).

virustotal_firstname


Solution

To send a character sequence to the First name field you have to use shadowRoot.querySelector() and you can use the following Locator Strategy:

  • Code Block:

    from selenium import webdriver
    import time
    
    options = webdriver.ChromeOptions() 
    options.add_argument("start-maximized")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
    driver.get("https://www.virustotal.com/gui/join-us")
    time.sleep(7)
    first_name = driver.execute_script("return document.querySelector('vt-virustotal-app').shadowRoot.querySelector('join-us-view.iron-selected').shadowRoot.querySelector('vt-ui-two-column-hero-layout').querySelector('vt-ui-text-input#first_name').shadowRoot.querySelector('input#input')")
    first_name.send_keys("Muhammad Aamir")
    
  • Browser Snapshot:

virustotal_firstname_filled


References

You can find a couple of relevant discussions in:

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
2

If you look at the HTML of the website, you can see that your input field is within a so called #shadowroot.

enter image description here

These shadowroots prevent you from finding the elements contained within the shadowroot using a simple find_element_by_id. You can fix this by finding all the parent shadowroots that contain the element you are looking for. In each of the shadowroots you will need to use javascript's querySelector and find the next shadowroot, until you can access the element you were looking for.

In your case you would need to do the following:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
driver =webdriver.Chrome()
driver.get('https://www.virustotal.com/gui/join-us')
print(driver.title)

# wait a bit untill form pops up
time.sleep(3)

# Retrieve the last shadowroot using javascript
javascript = """return document
.querySelector('vt-virustotal-app').shadowRoot
.querySelector('join-us-view').shadowRoot
.querySelector('vt-ui-text-input').shadowRoot"""
shadow_root = driver.execute_script(javascript)


# Find the input box
search = shadow_root.find_element_by_id("input")
search.send_keys("Muhammad Aamir")
search.send_keys(Keys.RETURN)
time.sleep(5)
driver.quit()

Daan Klijn
  • 1,269
  • 3
  • 11
  • 28