Home > Software engineering >  Selenium and Python Error: Message: invalid argument: 'using' must be a string
Selenium and Python Error: Message: invalid argument: 'using' must be a string

Time:08-22

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)

CodePudding user response:

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

CodePudding user response:

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.

  • Related