Selenium and Python Error: Message: invalid argument: 'using' must be a string

Question:

I’m trying to find the destination input box on the Google Flights page using Selenium. The box itself doesn’t have any useful identifiers (unless selenium can us jsname to find elements). Right now I’m using a locator to make selenium choose between two c-wiz boxes and I get this error:

selenium.common.exceptions.InvalidArgumentException: Message: invalid argument: 'using' must be a string

I guess I’m not exactly sure how to use a relative locator? My ultimate goal is to get Selenium to send the text "JFK" to the destination input box on https://www.google.com/travel/flights so if anyone has a more elegant approach I’m all ears 🙂

Here’s my code for reference:

bigWiz = bigBody.find_elements(wizLoc)" 

is throwing the error:

Code trials:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.relative_locator import locate_with

driver_service = Service(executable_path = '/path/chromedriver')
url = 'https://www.google.com/travel/flights'
browser = webdriver.Chrome(service = driver_service)
browser.get(url)
bigBody = browser.find_element(By.ID,'yDmH0d')
wrongWiz = bigBody.find_element(By.ID, 'ow4')
wizLoc = browser.find_element(locate_with(By.TAG_NAME, 'c-wiz').below(wrongWiz))
bigWiz = bigBody.find_elements(wizLoc)
Asked By: Fox

||

Answers:

The destination input box on the Google Flights page is a dynamic element.

To send a character sequence to the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:

  • Using XPATH:

    driver.get('https://www.google.com/travel/flights')
    driver.find_element(By.XPATH, "//div[@aria-label='Enter your destination']//preceding-sibling::div[1]//input").click()
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@aria-label='Enter your destination']//preceding-sibling::div[1]//input"))).send_keys("JFK")
    
  • 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
    
  • Browser Snapshot:

GoogleFlightsDestination

Answered By: undetected Selenium

You can actually use jsname in a locator, e.g. a CSS selector would be input[jsname='yrriRe']. The problem is that it finds 8 elements on the page so it’s not useful in this case.

You can do this a couple ways.

Active element

When the page first loads, the cursor is actually in the element you want so you can use simply

driver.switch_to.active_element.click()
driver.switch_to.active_element.send_keys("DFW")

NOTE: The active element changes after the click so you have to refetch it in the second line.

CSS selector

You can also use CSS selectors to find it.

wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div[aria-placeholder='Where to?'] input"))).send_keys("DFW")
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div[aria-label='Enter your destination'] input"))).send_keys("DFW")

NOTE: You should always prefer CSS selectors over XPaths because they are better supported, faster, and most times easier to read because the syntax is simpler.

Answered By: JeffC