0

I wrote a python script that goes to a site, and interacts with some dropdowns. It works perfectly fine if after I run the script, quickly make the browser instance full screen so that the elements are in view. If I don't do that, I get the error "Element could not be scrolled into view".

Here is my script:

from selenium import webdriver
driver = webdriver.Firefox()

driver.get("https://example.com")
driver.implicitly_wait(5)

yearbtn = driver.find_element("id", "dropdown_year")
yearbtn.click()
year = driver.find_element("css selector", '#dropdown_ul_year li:nth-child(5)')
year.click()

makebtn = driver.find_element("id", "dropdown_make")
makebtn.click()
make = driver.find_element("css selector", '#dropdown_ul_make li:nth-child(2)')
make.click()

modelbtn = driver.find_element("id", "dropdown_model")
modelbtn.click()
model = driver.find_element("css selector", '#dropdown_ul_model li:nth-child(2)')
model.click()

trimbtn = driver.find_element("id", "dropdown_trim")
trimbtn.click()
trim = driver.find_element("css selector", '#dropdown_ul_trim li:nth-child(2)')
trim.click()

vehicle = driver.find_element("css selector", '#vehiclecontainer > div > p')
vdata = driver.find_element("css selector", '.top-sect .tow-row:nth-child(2)')

print("--------------")
print("Your Vehicle: " + vehicle.text)
print("Vehicle Data: " + vdata.text)
print("--------------")
print("")

driver.close()

Like I said, it works fine if I make the browser full-screen (or manually scroll) so that the elements in question are in view. It finds the element, so what's the issue here? I've tried both Firefox and Chrome.

Andrew
  • 379
  • 1
  • 2
  • 13
  • Without seeing the site itself, my best guess would be that the element that you are trying to interact with is in some sort of IFRAME or part of the page with a scrollbar (not linked to the page scrollbar). – JeffC Jan 27 '23 at 21:26
  • Post the URL, without the URL we can't debug this type of question. – AbiSaran Jan 28 '23 at 02:29
  • @Prophet OP posted the problem clearly, the error message, and the code being used. What debugging details is it missing? – JeffC Jan 28 '23 at 21:27
  • @JeffC Your comment is starting with `Without seeing the site itself, my best guess would be` so, you are missing a link to there. But OK, maybe I misunderstood you – Prophet Jan 28 '23 at 21:45
  • @Prophet A link to the site is nice but not required. – JeffC Jan 28 '23 at 23:48
  • @JeffC The elements in question are simple HTML right on the page. When I run the script, the browser opens, and I have to manually scroll down to these 4 buttons to make them visible on the screen for the code to work error-free. The other option is to quickly full-screen the browser to my external monitor which is quite large. Is that normal python behavior? It's a bit confusing why I have to manually scroll the elements into the viewport. Like... what if the element was in a spot that isn't visible even when in full-screen? – Andrew Jan 30 '23 at 17:08
  • @AndrewMcCracken I've found that sometimes the page scrolls where other times it doesn't. To take care of the inconsistency, I use generic methods for common actions like `click()` where I do a wait, scroll, etc. and then call that everywhere. I've added an answer with a sample method. Try it and see if it fixes your issue. – JeffC Jan 30 '23 at 17:31

2 Answers2

0

Generally opens in maximized mode. Incase for specific version of it doesn't, the best practice is to open it in maximized mode as follows:

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

options = Options()
options.add_argument("start-maximized")
driver = webdriver.Firefox(options=options)

However in somecases the desired element may not get rendered within the due coarse, so you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following locator strategies:

vehicle = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#vehiclecontainer > div > p")))
vdata = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".top-sect .tow-row:nth-child(2)")))

print("--------------")
print("Your Vehicle: " + vehicle.text)
print("Vehicle Data: " + vdata.text)
print("--------------")
print("")
  • Note : You have to add the following imports :

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

You can find a relevant discussion in How to retrieve the text of a WebElement using Selenium - Python

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

I'm not sure what all is happening on the page in question. I use a generic method to take care of common actions like click(), find(), etc. that contain a wait, scroll, and whatever else is useful for that action. I've put an example below. It waits for the element to be clickable (always a best practice), scrolls to the element, and then clicks it. You may want to tweak it to your specific use but it will get you pointed in the right direction.

def click(self, locator):
    element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable(locator))
    driver.execute_script("arguments[0].scrollIntoView();", element)
    element.click()

I would suggest you try this and then convert all of your clicks to use this method and see if that helps, e.g.

click((By.ID, "dropdown_year"))

or

locator = (By.ID, "dropdown_year")
click(locator)
JeffC
  • 22,180
  • 5
  • 32
  • 55