Selenium 4. find_element_by_css_selector not working - selenium

Based on the Selenium documentation the find element by css selector syntax is element = driver.find_element_by_css_selector('#foo') but the example shows there is a.nav before the # sign ‘(a.nav#home)’ which based on this website is HTML tag.
In another part of the Selenium documentation the css_selector even doesn't have the # sign: ele = driver.find_element(By.CSS_SELECTOR, 'h1')
Questions:
Which syntax is correct? with or without the HTML tag? with or without the # sign?
In Visual Studio Code I used these syntaxes to find the search boxes or sign-in boxes. It worked in this website but didn't work in this website. Could you help me find the search box using css_selector in this website?
Here is an example of my scripts:
from selenium import webdriver
from selenium.webdriver.common.by import By
try:
driver = webdriver.Chrome()
driver.get("https://www.arizonarealestate.com")
searchBox = driver.find_element(By.CSS_SELECTOR, "#input[placeholder='Enter city, address, neighborhood, zip, or MLS #']")
searchBox = driver.find_element(By.CSS_SELECTOR, "input#input[placeholder='Enter city, address, neighborhood, zip, or MLS #']")
searchBox.send_keys("Some text")
searchBtn = driver.find_element(By.CSS_SELECTOR, "button#.btn.btn-primary.btn-lg.btn-block.js-qs-btn").click()
finally:
#print("============ Done!")
driver.quit()

Generally speaking a css selector is just a string with some specific syntax and is not really defined by the selenium WebDriver itself.
You should have a look at the MDN description of css selectors.
In your question you specifically seem to have question on where to specify the id selector specified with the # character. This selector should actually only be used just by itself as all id's in a page should be unique and therefore no other information is needed.
In your example, the css selector #input[placeholder=...'] selector would select an element with an id equal to input.
If you intended selecting an input tag with a specific placeholder you should omit the #.

Related

How to find Xpath of any "city" of variable dropdown?

I installed Chrome addon "Selectors Hub".
I opened site: spicejet.com
I choose some random city of "from" dropdown.
With help of "Selectors Hub" chrome addon, I grabbed the Xpath code of
that city:
//div[#class='css-1dbjc4n r-14lw9ot r-z2wwpe r-vgw6uq r-156q2ks r-urutk0 r-8uuktl r-136ojw6']//div[11]
While validating this Xpath code in console, it shows 0 matches.
This website is built on ReactJs as front-end, if I am not wrong, and finding the elements of a ReactJs website is a bit challenging; adding to that, if you rely on some locator finding tool, it's gets more difficult. It's always better you build your own locator strategy than rely on tools, especially for websites built with React, Vue, etc.
Having said that, the strategy here is to find the relatively narrowed down relative locator, and then since you are looking for a random selection of city, collect all the cities first, then apply random to it. Here is what it figured:
I collected cities, but along with it came some unwanted items (courtesy my relative locator), and I check them and if they are picked up, I pass them out, and only when a city is selected by random, I click on it. Check this code:
import random
driver.get("https://www.spicejet.com/")
time.sleep(10)
driver.find_element(By.XPATH, "//div[#data-testid='to-testID-destination']").click()
time.sleep(2)
cities = driver.find_elements(By.XPATH, "//div[#data-testid='to-testID-destination']//div[#data-focusable='true']")
print(len(cities))
x = random.choice(cities)
if x.text in ['To', 'India', 'International']:
pass
else:
print(x.text)
x.click()
time.sleep(5)
driver.quit()
Output:
Pakyong
Pakyong Airport
PYG
Process finished with exit code 0

Selecting elements using xpath

So very new here to Selenium but I'm having trouble selecting the element I want from this website. In this case, I got the x_path using Chrome's 'copy XPath tool.' Basically, I'm looking to extract the CID text (in this case 4004) from the website, but my code seems to be unable to do this. Any help would be appreciated!
I have also tried using the CSS selector method as well but it returns the same error.
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.binary_location = '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary'
driver= webdriver.Chrome()
chem_name = "D008294"
url = "https://pubchem.ncbi.nlm.nih.gov/#query=" + chem_name
driver.get(url)
elements = driver.find_elements_by_xpath('//*[#id="collection-results-container"]/div/div/div[2]/ul/li/div/div/div/div[2]/div[2]/div[2]/span/a/span/span')
driver.close()
print(elements.text)
As of now, this is the error I receive: 'list' object has no attribute 'text'
Here is the xpath that you can use.
//span[.='Compound CID']//following-sibling::a/descendant::span[2]
Why your script did not worked: I 2 issues in your code.
elements = driver.find_elements_by_xpath('//*[#id="collection-results-container"]/div/div/div[2]/ul/li/div/div/div/div[2]/div[2]/div[2]/span/a/span/span')
driver.close() # <== don't close the browser until you are done with all your steps on the browser or elements
print(elements.text) # <== you can not get text from list (python will through error here
How to fix it:
CID = driver.find_element_by_xpath("//span[.='Compound CID']//following-sibling::a/descendant::span[2]").text # <== returning the text using find_element (not find_elements)
driver.close()
print(CID) # <== now you can print `CID` though browser closed as the value already stored in variable.
Function driver.find_elements_by_xpath return list of Element. You should loop to get text of each element,
Like this:
for ele in print(elements.text):
print(ele.text)
Or if you want to match first Element, use driver.find_element_by_xpath function instead.
Using xpath provided chrome is always does not work as expected. First you have to know how to write xpath and verify it chrome console.
see these links, which helps you to know about xpaths
https://www.guru99.com/xpath-selenium.html
https://www.w3schools.com/xml/xpath_syntax.asp
In this case, first find the span contains text Compound CID and move to parent span the down to child a/span/span. something like //span[contains(text(),'Compound CID']/parent::span/a/span/span.
And also you need to findelement which return single element and get text from it. If you use findelements then it will return list of elements, so you need to loop and get text from those elements.
xpath: //a[contains(#href, 'compound')]/span[#class='breakword']/span
you can use the "href" as your attribute reference since I noticed that it has unique value for each component.
Example:
href="https://pubchem.ncbi.nlm.nih.gov/substance/53790330"
href="https://pubchem.ncbi.nlm.nih.gov/compound/4004"

How to locate ALL html tags in Selenium with Python

My code:
import stuff...
driver = webdriver.Firefox(executable_path='C:\\...\\geckodriver.exe')
driver.get('https://webpage.com/')
elems = driver.find_elements_by_CLASS_ID_TEXT_XPATH_WHATEVER_ELSE_BADLY_DOCUMENTED_STUFF
How do I get a list of ALL CSS Selectors, such as Class, ID, p, span, input, button and all other elements from the webpage.com?
If you know a link to a brief and clear info resource with plentiful of examples explaining find_elements_by or Locating Elements in advanced detail, please share here.
edit:
ok, a bit more specific question then, how could I get the list of ALL Class Selectors from a webpage into elems?
elems = driver.find_elements_by_class_name('????')
You could use XPath to search the DOM, there's a good tutorial on using XPath here. You may also find this resource useful which covers using XPath queries with Selenium.
You can use XPath queries with selenium like so:
elements = driver.find_elements(By.XPATH, '//button')
This code would return all buttons on the page.
elements = driver.find_elements(By.XPATH, '[class]')
This would return all the elements that contain a class attribute
I hope this helps.

How to read ol and li elements dynamically without using xpath

I'm new to selenium and Below is my HTML and i want to display sons of Dhritrashtra and grandsons of pandu (without using xpath). I've tried methods like getText and getLinkText but it's not working for me. Please help.Thanks.
Kuru
Shantanu
Vichitravirya
Dhritrashtra
DuryodhanaDushasanaDussalanJalagandhaSamaSahaVindhaAnuvindhaDurmukhaChitrasenaDurdarshaDurmarshaDussahaDurmadaVikarnaDushkarnaDurdharaVivinsatiDurmarshanaDurvishahaDurvimochanaDushpradharshaDurjayaJaitraBhurivalaRaviJayatsenaSujataSrutavanSrutantaJayatChitraUpachitraCharuchitraChitrakshaSarasanaChitrayudhaChitravarmanSuvarmaSudarsanaDhanurgrahaVivitsuSubaahuNandaUpanandaKrathaVatavegaNishaginKavashinPaasiVikataSomaSuvarchasasDhanurdharaAyobaahuMahabaahuChithraamgaChithrakundalaBheemarathaBheemavegaBheemabelaUgraayudhaKundhaadharaVrindaarakaDridhavarmaDridhakshathraDridhasandhaJaraasandhaSathyasandhaSadaasuvaakUgrasravasUgrasenaSenaanyAparaajithaKundhasaaiDridhahasthaSuhasthaSuvarchaAadithyakethuUgrasaaiKavachyKradhanaKundhyBheemavikraAlolupaAbhayaDhridhakarmaavuDhridharathaasrayaAnaadhrushyaKundhabhedyViraavyChithrakundalaPradhamaAmapramaadhyDeerkharomaSuveeryavaanDheerkhabaahuKaanchanadhwajaKundhaasyVirajas
Pandu
Yudhishtir
Prativindhya
Bhim
Sutasoma
Ghatotkch
Arjun
Srutakirti
Babhruvahan
Nakul
Satanika
Sahadev
Shrutkarma
Here is the solution for your query:
It's not mandatory to use xpath always. As per the Selenium Documentation & standards, consider the following attributes in sequence: id, name, css, linktext, xpath. If still unable to detect the element try for css/xpath with multiple attributes like class, src, etc.
Once you can identify the element then only you will be able to retrieve the properties of the element like getText() & getLinkText().
Most important, you have provided the copy of the text from the website. It's impossible to identify an an element from the website text to help you out. You need to provide some relevant part of the HTML DOM inorder to enable us to help you. You can look into the PageSource of any webpage to know the properties (id/name/css/xpath) of the elements. For that, while you are on a webpage, you can right-click and select "View Page Source". For Mozilla Firefox you can download & install extensions ​like Firepath & Firebug to know the properties of an element.
Finally you have to write some code either in Java/Python/C# to open a browser through Selenium of your choice, open a website and perform certain actions with different elements present on the webpage.
Let me know if this answers your question.
I don't know the exact syntax your html has but You can use cssSelector as below per my assumptions of your html elements for both your queries:
1) ul ol ol ol li:nth-child(n) - n= element index
2) ul ol ol ol:nth-child(2) li:nth-child(n) li:nth-child(1) - n= element index

When and how can I locate an element by tag name using Selenium WebDriver? Please explain with an example

I have used most of the element locators while testing with Selenium, but very low frequently used the 'TagName' locator. Please give an example.
Now supposing, a software web element does not have any ID or Class Name, then how can we locate that element in Selenium WebDriver? The answer is there are many alternatives of the Selenium WebDriver element locators and one of them is locating an element by tag name.
Locating an element by tag name is not too much popular because in most of cases, we will have other alternatives of element locators. But yes, if there is not any alternative then you can use the element's DOM tag name to locate that element in webdriver.
Here you can select the tagname as a locator like:
// Locating the element by tagName and store its text in variable 'dropdown'.
String dropdown = driver.findElement(By.tagName("select")).getText();
Thanks to the deprecation of By.tagName you should use By.css for Shah's answer...
String dropdown = driver.findElement(By.css("select")).getText();
We use the actual name of the tag like <a> for anchor and <table> for table and input for <input>. This helps to get all the elements with a given tag name.
Example: to select the first element of a given input
var dialog = driver.FindElement(By.ClassName("ladialog"));
var save = dialog.FindElements(By.TagName("input"))[0];
save.Click();
Also importantly, the tagName locating strategy can be used to get or fetch all the links on a webpage and print them to console. Try this:
// Get all links in a webpage
List<WebElement> allLinks = driver.findElements(By.tagName("a"));
System.out.println("Links count is: " + allLinks.size());
for(WebElement link : allLinks)
System.out.println(link.getText());