Hi all. I'm trying to use Selenium to find an element by CSS selector and although I've tried using the documentation, I think I'm misunderstanding something.
This is what I'm trying:
driver.find_element(By.CSS_SELECTOR,f"img [src='images/icons/new.gif'][alt='Add new item to list']").click()
This is the element I want to find and click:
<img src="images/icons/new.gif" alt="Add new item to list">
The error I get is as follows:
Exception has occurred: NoSuchElementException
Message: no such element: Unable to locate element: {"method":"css selector","selector":"img [src='images/icons/new.gif'][alt='Add new item to list']"}I can see it's on the page, however, so I'm not sure what I'm missing. I can find other items using XPATH and ID so selenium is up and running, just to rule that out. Can anybody suggest anything?
(I'm using selenium 4.8.2 and python 3.11.1, if that helps)
html - How to loop multiple elements in python selenium (different CSS selectors) - Stack Overflow
Pulling multiple elements from the same page
python - find_element_by_class_name for multiple classes - Stack Overflow
Selenium with Python - find elements of more than one css class - Stack Overflow
Videos
So I am making a Garmin crawling script and I want it to pull multiple elements if they are from the same day and add the time together for some activities, time, distance and heart rate for another for example.
Layout of website
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import login as login
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import datetime
import time
x = datetime.datetime.now()
x = x.strftime("%b %d")
driver = browser = webdriver.Firefox()
driver.get("https://connect.garmin.com/modern/activities")
driver.implicitly_wait(1)
iframe = driver.find_element(By.ID, "gauth-widget-frame-gauth-widget")
driver.switch_to.frame(iframe)
driver.find_element("name", "username").send_keys(login.username)
driver.find_element("name", "password").send_keys(login.password)
driver.find_element("name", "password").send_keys(Keys.RETURN)
driver.switch_to.default_content()
time.sleep(10)
driver.find_element("name", "search").send_keys("Reading")
driver.find_element("name", "search").send_keys(Keys.RETURN)
time.sleep(2)
element = driver.find_element(By.CSS_SELECTOR, '.activity-date > span:nth-child(1)').text
time.sleep(2)
print(element)
time_read = 0
if element == x:
spent = driver.find_element(By.CSS_SELECTOR, 'li.list-item:nth-child(1) > div:nth-child(2) > div:nth-child(5) > div:nth-child(2) > span:nth-child(1) > span:nth-child(1)').text
result = time.strptime(spent, "%H:%M:%S")
time_read += result.tm_hour * 60
time_read += result.tm_min
print(time_read)
So this is my current code. It finds the date, checks if it is today and adds the minutes to the variable time_read.
Now I need some help in how I go about adding multiple elements, and if this can be done with some kind of for loop, where it loops between the dates and can then extract the time from the element?
Do I need to set them up one by one, since I need to provide which element a specific iteration needs to pull from? So maybe I should have 5 or 6 checks for example, instead of some kind of loop that goes through and does it? Then it will be a lot of manual work, which makes me question if there isn't a better way to deal with it.
I do not want to use CSV.
Some relevant HTML
<div class="pull-left activity-date date-col">
<span class="unit">Sep 14</span>
<span class="label">2022</span>
</div>
<span class="unit" title="3:32:00"><span class="" data-placement="top" title="3:32:00">3:32:00</span></span>
<span class="unit" title="1:00:00"><span class="" data-placement="top" title="1:00:00">1:00:00</span></span>
<span class="" data-placement="top" title="1:00:00">1:00:00</span>Also a bit unsure what the best way is to locate elements? Is CSS.SELECTOR good or should I use XPATH preferably?
Thanks
To select the div with the class you can use css (preferred for readability)
BY.css
Example
driver.find_element(By.CSS, 'div.dept-time')
or xpath
BY.xpath
Example
driver.find_element(By.XPATH, '//div[@class=dept-time]
or if there are multiple classes for that element, use
contains
Example
//div[contains(@class, 'dept-time')]
If more than 1 div element with that class exist and you want the first one you can also use:
[1]
Example (XPATH)
//div[@class='dept-time'])[1]
Example (CSS)
div.dept-time:first
Using css selectors, instead of class, the syntax to select the tag with a specific class/attribute is tag[attribute='value']. So in your case:
[element.text for element in self.browser.find_elements(By.CSS_SELECTOR, "div[class='dept-time']")]
More information on css selectors: https://www.w3schools.com/cssref/css_selectors.asp