Home > front end >  Finding elements by Class returning blank list
Finding elements by Class returning blank list

Time:08-16

I have a code to pull the vessels from this website:

'https://signal.portoptimizer.com/'

I was able to open the table with the vessels using

arrow_icon = self.driver.find_element('xpath','/html/body/app-root/app-pure-frame/div/div/div/app-signal2-page/div/div/app-current-inbound-vessels/div/app-widget-card/div/div[2]/div/mat-expansion-panel/mat-expansion-panel-header/span[2]')
arrow_icon.click()

but now I want to have a list with all vessesls, tried with the below but it is showing no value in the list:

all_vessels = self.driver.find_elements(By.CLASS_NAME,"anchorage-by-terminal")
print(all_vessels)

What would be the issue?

CodePudding user response:

You want to find a class given only part of the name (in this case the beginning). You can do this with CSS selectors:

self.driver.find_elements(By.CSS_SELECTOR, "div[class^='anchorage-by-terminal']")

More generally, you can find an element with an attribute starting with some text with

self.driver.find_elements(By.CSS_SELECTOR, "element[attribute^='start-text']")

Ending with some text as:

self.driver.find_elements(By.CSS_SELECTOR, "element[attribute$='end-text']")

And containing some text as:

self.driver.find_elements(By.CSS_SELECTOR, "element[attribute*='anywhere-text']")

CodePudding user response:

You can get all the the vessel names as following:
First get all the table rows and then get each row first cell text, like this:

rows = self.driver.find_elements(By.CSS_SELECTOR,"datatable-row-wrapper datatable-body-row")
for row in row:
    name = row.find_element(By.CSS_SELECTOR,"span.anchorage-by-terminal-table-cell-content").text
    print(name)

"span.anchorage-by-terminal-table-cell-content" is not a unique locator for the first cell in the row, but since we are looking for a first call in each row this will work here.
Also, don't forget using delays, preferably expected conditions explicit waits to make page / elements loaded before you access them.
UPD
In order to get non-first cell content you will have to mention the explicit matching locator index.
For example to get Expected date of Berth you can do this:

rows = self.driver.find_elements(By.CSS_SELECTOR,"datatable-row-wrapper datatable-body-row")
for row in row:
    berth = row.find_element(By.XPATH,"(.//span[contains(@class,'pure-frame-cell-content')])[3]").text
    print(berth)

Pay attention, these cells having different class name but it is not unique too

CodePudding user response:

To extract the Vessel Names from the website you have to induce WebDriverWait for visibility_of_all_elements_located() and using List Slising you can use either of the following locator strategies:

  • Using CSS_SELECTOR:

    driver.execute("get", {'url': 'https://signal.portoptimizer.com/'})
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//mat-panel-title[normalize-space()='Click to view inbound vessels']"))).click()
    print([my_elem.text for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "span.anchorage-by-terminal-table-cell-content")))[::4]])
    
  • Using XPATH:

    driver.execute("get", {'url': 'https://signal.portoptimizer.com/'})
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//mat-panel-title[normalize-space()='Click to view inbound vessels']"))).click()
    print([my_elem.text for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[contains(@class, 'anchorage-by-terminal-table-cell-content')]")))[::4]])
    
  • 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
    
  • Console Output:

    ['CMA CGM PANAMA', 'ARISTOMENIS', 'CMA CGM DIGNITY', 'MSC ARIANE', 'YM UBIQUITY', 'MAERSK EUREKA', 'MSC SAVONA', 'CMA CGM SYMI', 'YM TUTORIAL']
    
  • Related