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']