Selenium: How do I check the src attribute of an image? - selenium

I'm trying to check the value of the src attribute for this image (highlighted in blue):
This is what I'm trying (not working):
visual = col_12_wrapper.find_element_by_class_name('visual')
left_text_img = visual.find_element_by_css_selector('div.col-sm-6:first-of-type')
left_img = left_text_img.find_element_by_tag_name('img')
#this line below fails
left_img[contains(#src,'../../static/images/databytes/colors/frame-0164.jpg')]

This line:
left_img[contains(#src,'../../static/images/databytes/colors/frame-0164.jpg')]
Is trying to use an XPATH as an index.
you would need to use find_element like so:
left_img.find_element_by_xpath(".//*[contains(#src, '../../static/images/databytes/colors/frame-0164.jpg')]")
I would recommend a more direct path of finding this element though:
direct_path = driver.find_element_by_xpath(".//div[#class='visual']/div[#class='col-sm-6']//img[#class='color-frame' and contains(#src, 'frame-0164.jpg')]")
If you want to get the element and then check it's src attribute, try this:
direct_path = driver.find_element_by_xpath(".//div[#class='visual']/div[#class='col-sm-6']//img[#class='color-frame']")
src_attribute = direct_path.get_attribute('src')
SIDENOTE: Based on your error message in the comments, you are running on an old chromedriver 2.35 which does not support your current version of Chrome 67, please go HERE to update your chromedriver as well. Recommended for build 67 is current chromedriver 2.40.

You can try with this code : [you can get the src attribute from the DOM like this and it's always good to use WebDriverWait]
img = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, 'div.color-squares.squares-20+img')))
source = img.get_attribute("src")
print(source)
Note that you will have to import these :
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
In case you are looking for xpath , that would be :
//div[contains(#class,'color-squares squares-20')]/following-sibling::img

Below is the XPath of the img element
//img[#class='color-frame'][contains(#src,'frame-0164.jpg')]

Related

select element in selenium using partial xcode or partial css selector

I am trying to select a certain element in a webpage in selenium. I know that the element's name looks like person_xxxxx with xxxx being random numbers. I would like to know if it is possible to select this element using xpath or css selector. So far I have tried:
cartes_profils=liste_profils_shadow.find_elements_by_xpath('//*[contains(#id,"person_")]')
which is deprecated and doesn't work
cartes_profils=liste_profils_shadow.find_elements(by=By.CSS_SELECTOR,value='input[id^="#person_"]')
which runs but doesn't select the desired elements
cartes_profils=liste_profils_shadow.find_elements(by=By.XPATH,value=("//*[contains(#id, 'person_')]"))
which returns an "invalid selector" error
PS: I know that there are similar topics already answered but they are all a million years old and the solutions do not work for me
You should ideally be using starts-with for xpath. Also, yes you are right
find_elements_by_*** is deprecated in selenium 4. You should use find_element(By.XPATH, "")
so your effective xpath would be:
//*[starts-with(#id,'person_')]
use it like
driver.find_element(By.XPATH, "//*[starts-with(#id,'person_')]")
and equivalent CSS would be: (you are fairly close here)
input[id^="person_"]
use it like
driver.find_element(By.CSS_SELECTOR, "input[id^="person_"]")
My recommendation would be explicit waits:
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[starts-with(#id,'person_')]")))
You'll have to import these for explicit waits:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

How can I click on the third element in this list using selenium? I have tried everything and nothing works

I am running a webscraper and I am not able to click on the third element. I am not sure what to do as I have tried googling and running several types of code.
Below is a screenshot of the html and my code. I need the third element in the list to be clicked on. It is highlighted in the screenshot. I am not sure what to do with the css and data-bind
here is the code for max bed options. I also need to get the 2 beds just like we did for min bed options
thanks!!
According to the picture the following should work:
driver.find_element_by_xpath('//span[#id="bedsMinMaxRangeControl"]//li[#data-value="2"]').click()
But we need to see the entire page HTML to give a correct answer.
Also don't forget to use delays/ waits there.
UPD
For the new question the code will be:
driver.find_element_by_xpath('//span[#id="bedsMinMaxRangeControl"]//ul[contains(#class,"maxBedOptions")]//li[#data-value="2"]').click()
Here you should also use the appropriate data-value that has values from -1 up to 3
You can use css_selector with the data-value attribute.
locator = ".dropdownContent .minBedOptions li[data-value='2']"
WebDriverWait(driver, 10).until((EC.element_to_be_clickable, (By.CSS_SELECTOR, locator))).click()
I used WebDriverWait so make sure to import it...
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
If it's just a list using li tags as it seems from the shared snap, You could probably write the easiest xpath as :
//li[contains(text(), '2 Beds')]
and use it like this :
driver.find_element_by_xpath("//li[contains(text(), '2 Beds')]").click()
or if you want to use xpath in conjunction of WebDriverWait, use it like this :
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.XPATH, "//li[contains(text(), '2 Beds')]")))
Import :
from selenium.webdriver.support import expected_conditions as EC
Now let's talk about when we do not want to be dependent on 2 Beds text in XPATH, cause if text changes in the UI, we'd have to change the locator in Selenium-Python bindings.
A good way to do is to :
Make use of data-value attribute : //li[#data-value = '2']
Make use of ul and li tags : //ul[contains(#class, 'minBedOptions')/li[#data-value = '2']]

Selenium access table by xpath

i'm fairly new to selenium and i'm building a scraper to extract info from a table.
I'm able to acces the table body by ID with no problem but when I try to access it's children they are not found.
the inspector shows the xpath for the first cell as //*[#id="tb_list"]/tr[1]/td[1] but
find_element_by_xpath(//*[#id="tb_list"]/tr[1]/td[1])
can't find it.
I also tried the following to no avail.
table = driver.find_element_by_id("tb_list")
table.find_element_by_xpath(".//tr[1]/td[1]")
it's able to find tb_list but fails to locate the children
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":".//tr[1]/td[1]"}
Everywhere I looked people suggest one of these 2 methods, what am I doing wrong? The table is dynamically populated from a database, could this be an issue?
I'm using python and the chrome web driver,
I'm hesitant to give a snippet of the html as the site is not publicly available and i dont own it.
[1] indicates first descendent. So the xpath:
//*[#id="tb_list"]/tr[1]/td[1]
can be optimized as:
//*[#id="tb_list"]/tr/td
Effectively the line of code would be:
driver.find_element(By.XPATH, "//*[#id='tb_list']/tr/td")
Ideally, to locate the element you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using XPATH:
element = WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//*[#id='tb_list']/tr/td")))
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

find_element_by_class_name in selenium giving error

I am trying to automate a button click using selenium but it is giving me the error. The html code of the page is:
The code i am trying is:
create_team=driver.find_element_by_class_name('ts-btn ts-btn-fluent ts-btn-fluent-secondary ts-btn-fluent-with-icon join-team-button')
create_team.click()
I am getting the following error:
driver.find_element_by_class_name() only accepts one className, it's not built to handle multiple classNames, reference - (How to locate an element with multiple class names?), THIS SEEMS TO BE UP FOR DEBATE
Use driver.find_element_by_css_selector('ts-btn.ts-btn-fluent.ts-btn-fluent-secondary.ts-btn-fluent-with-icon.join-team-button')
With driver.find_element_by_css_selector you can chain multiple classNames together using a dot(.) between each className in the selector.
To click on the element you can use either of the following Locator Strategies:
Using css_selector:
driver.find_element_by_css_selector("button.ts-btn.ts-btn-fluent.ts-btn-fluent-secondary.ts-btn-fluent-with-icon.join-team-button[data-tid='tg-discover-team']").click()
Using xpath:
driver.find_element_by_xpath("//button[#class='ts-btn ts-btn-fluent ts-btn-fluent-secondary ts-btn-fluent-with-icon join-team-button' and #data-tid='tg-discover-team']").click()
As the desired element is an Angular element, ideally to click on the element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.ts-btn.ts-btn-fluent.ts-btn-fluent-secondary.ts-btn-fluent-with-icon.join-team-button[data-tid='tg-discover-team']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='ts-btn ts-btn-fluent ts-btn-fluent-secondary ts-btn-fluent-with-icon join-team-button' and #data-tid='tg-discover-team']"))).click()
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
create_team=driver.find_element_by_class_name('ts-btn.ts-btn-fluent.ts-btn-fluent-secondary ts-btn-fluent-with-icon.join-team-button')
create_team.click()
You have to replace space with . as space indicate multiple class
You can use xpath or css also:
create_team=driver.find_element_by_xpath("//*[#class='ts-btn.ts-btn-fluent.ts-btn-fluent-secondary ts-btn-fluent-with-icon.join-team-button]')
create_team.click()
create_team=driver.find_element_by_css_selector("[class='ts-btn.ts-btn-fluent.ts-btn-fluent-secondary ts-btn-fluent-with-icon.join-team-button]')
create_team.click()
More to answer
If you check the exception from the by_class_name:
You can see that it is using css_class locator under the hood ( You can see it add . in frontautomatically)
Working example:
from selenium import webdriver
import time
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://stackoverflow.com/questions/65579491/find-element-by-class-name-in-selenium-giving-error/65579606?noredirect=1#comment115946541_65579606")
time.sleep(5)
elem = driver.find_element_by_class_name('overflow-x-auto.ml-auto.-secondary.grid.ai-center.list-reset.h100')
print(elem.get_attribute("outerHTML"))

Scrolling through pages with Python Selenium

I have written a python script that aims to take data off a website but I am unable to navigate and loop through pages to collect the links. The website is https://www.shearman.com/people? The Xpath on the site looks like this below;
ul class="results-pagination"
li class/a href onclick="PageRequest('2', event)"
When I run the query below is says that the element is not attached to the page;
try:
# this is navigate to next page
driver.find_element_by_xpath('//ul[#class="results-pagination"]/li/[#onclick=">"]').click()
time.sleep(5)
except NoSuchElementException:
break
Any ideas what I'm doing wrong on this?
Many thanks in advance.
Chris
You can try this code :
browser.get("https://www.shearman.com/people")
wait = WebDriverWait(browser, 30)
main_tab = browser.current_window_handle
navigation_buttons = browser.find_elements_by_xpath('//ul[#class="results-pagination"]//descendant::a')
size = len(navigation_buttons )
print ('this the length of list:',navigation_buttons )
i = 0
while i<size:
ActionChains(browser).key_down(Keys.CONTROL).click(navigation_buttons [i]).key_up(Keys.CONTROL).perform()
browser.switch_to_window(main_tab)
i=i+1;
if i >= size:
break
Make sure to import these :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
Note this will open each link in new tab. As per your requirement you can click on next button using this xpath : //ul[#class="results-pagination"]//descendant::a
If you want to open links one by one in same tab , then you will have to handle stale element reference as once you will be moved out from main page , all element will become stale.