Python Selenium accessing elements with similar classes - python

I am trying to click on this element using python-selenium bindings .There are multiple elements with the same class but different data-original-title attribute .
How can I access these elements with data-original-title="Like" directly ?
instead of having to fetch first by class names then loop through elements for desired attribute .
HTML code
<div class="IconContainer js-tooltip" data-original-title="Like">

If you meant that the attribute data-original-title is always unique, you can select the element with the desired attribute value using xpath:
//div[#data-original-title='Like']

Related

Python - Selenium get Element by attribute and the full attribute value

Hi how can I get an element by attribute and the attribute value in Python Selenium?
For example I have class="class1 class2 class3".
Now I want to get the element with the attribute class what ca.rries the classes "class1 class2 class3".
Is this possible?
If I use xpath, I always need to add the element type, input, option,...
I try to avoid the element type since it varies sometimes.
While constructing locators considering css-selectors or xpath you have to use the different attributes and the attribute-values to identify the WebElement uniquely within the DOM Tree.
The generic way is:
Using css_selector:
button.classname[attributeA='attributeA_value'][attributeB='attributeB_value']
Using xpath and attributes:
//button[#attributeA='attributeA_value'][#attributeB='attributeB_value']
As an example, for an element like:
<button type="button" aria-hidden="true" class="close alert alert-close" data-notify="dismiss">Close</button>
You can identify the Close element using either of it's the attributes and the corresponding attribute-values using either of the Locator Strategies:
Using css_selector:
button.close.alert.alert-close[data-notify='dismiss']
classes-> ^ ^^ ^^^ data-notify ^^^^ attribute
Using xpath and attributes:
//button[#class='close alert alert-close' and #data-notify='dismiss']
class attributes ^ ^^ ^^^ data-notify ^^^^ attribute
Using xpath and innerText:
//button[text()='Close']
innerText ^
The CSS selectors would be formatted like this:
'[attribute]'
'[attribute="value"]'
For example, the selector for the input field on google.com would be:
'input[name="q"]'
to answer this part
If I use xpath, I always need to add the element type, input,
option,... I try to avoid the element type since it varies sometimes.
you can use //* and then attribute type and attribute value.
//*[#class='class1 class2 class3']
//* represent any or all nodes

Python selenium wait until an element located not by xpath?

I am scraping a webpage in multiple pages, pressing certain buttons will advance to the next page, but all the pages share exactly the same url, means most elements I have scraped aren't visible until certain buttons of the same type before them are clicked, thus trying to click them will raise the following error:
ElementNotInteractableException: Message: Element <div class="answer"> could not be scrolled into view
The elements are all of the same class, and they are all children of instances of another class, each of the parent classes have multiple instances of the child class.
To find the elements, I use two times .find_elements_by_class_name() method:
lists = []
for i in Firefox.find_elements_by_class_name('parent'):
lists.append(i.find_elements_by_class_name('child')
There is exactly one element in each of the sublists that needs to be clicked, the element is determined by its attribute and identified using list indexing, so I have absolutely no idea what its xpath is.
Each of the elements aren't visible until the preceding element is clicked, so wait for them is a must to avoid ElementNotInteractableException.
I am using the following syntax:
wait = WebDriverWait(Firefox, 3)
wait.until(EC.visibility_of_element_located((By.XPATH, xpath)))
And I need to find the xpath of an element located using the aforementioned methods, unfortunately Selenium doesn't support this natively.
But I have found a trick here:
In [1]: el
Out[1]: <Element span at 0x109187f50>
In [2]: el.getroottree().getpath(el)
Out[2]: '/html/body/div/table[2]/tbody/tr[1]/td[3]/table[2]/tbody/tr/td[1]/p[4]/span'
So I think, if I can build lxml tree from selenium page source then somehow convert selenium elements into lxml elements then it can be done, though I don't know exactly how...
What about something like this (maybe you need to use contains for class):
wait.until(EC.visibility_of_element_located((By.XPATH, f'//*[#class="parent"][{index}]//*[#class="child"][{subindex}]')))

Selecting inner text when using find element by css selector python, selenium and create a loop

im trying to get all link text from a tag p and with a specific class. Then create a loop to find all other similar elements.
how it looks
so far i am using this :
the value i want is in
<div class='some other class'>
<p class='machine-name install-info-entry x-hidden-focus'> text i want
</p> ==$0
installations = browser.find_elements_by_css_selector('p.machine-name.install-info-entry.x-hidden-focus')
any help is appreciated. thanks.
You can just use .text
installations = browser.find_elements_by_css_selector('p.machine-name.install-info-entry.x-hidden-focus')
for installation in installations:
print(installation.text)
Note that installations is a list of web elements, whereas installation is just a web element from the list.
UPDATE1:
If you want to extract the attribute from a web element, then you can follow this code:
print(installation.get_attribute("attribute name"))
You should pass your desired attribute name in get_attribute method.
You can read innerHTML attribute to get source of the content of the element or outerHTML for source with the current element.
installation.get_attribute('innerHTML')
Hope this will be helpful.

How to select one element with common class names in Selenium Webdriver using Python?

I'm new to Selenium Webdriver using Python.
I want to select the tag which contains 'Stats'. Tried multiple ways but failed as both the tags don't have any Id and have same class names as well.
Please help me with the codes to select the tag which contains 'Stats' using Selenium webdriver with python.
List of few Trials, Even if the result is found. I'm unable to click it and the error message is Lists cannot be clicked.
driver.find_element_by_class_name("css173kae7").click()
driver.find_elements_by_link_text("stats/dashboard").click()
driver.find_elements_by_xpath("//*[contains(text(), 'Stats')]")
I've attached the image of the Inspect element of the code, please have a look at it.
(Updated) Image
Inspect element of the "Anchor Tags" from which one needs to be selected
Use this code:
driver.find_elements_by_xpath("//*[contains(text(), 'stats')]")
if you are looking for "stats" in href attribute use below code:
driver.find_elements_by_xpath("//*[contains(#href, 'stats')]")
Keep in mind, contains is case-sensitive.
If you want to do case-insensitive search, See here.
Based on the image of the HTML you shared, I would try this XPATH locator to select that element:
driver.find_element_by_xpath(".//a[#class='css-1qdedno' and #href='/stats/dashboard']")
try this xpath
//nav//a[contains(#href,'/stats/dashboard')]
You need to select the desired element by its index value after you get all the elements in a list:
elements= driver.find_elements_by_xpath("//*[contains(text(), 'stats')]")
Then identify and access the element by its index and call the click() function:
For example if the element is at elements[0], then
elements[0].click()

Iterate through multiple class using find_element_by_class_name in Selenium

I am using Selenium webdriver in Python for a web-scraping project.
The webpage, I am working on has a number of Table entries with the same class name.
<table class="table1 text print">
I am using find_element_by_class_name. However I am getting a error :
*Compound class names not permitted *
Another question:
How to iterate through all the tables having the same css classname ?
Thanks
You should use find_elements_by_class_name. This will return an iterable object.
The error you describe happens when you provide multiple class names rather than a single one. An easy way around this is to get the elements using CSSSelector or XPath. Alternatively, you could use find_elements_by_class_name and provide one class name, then iterate through that list to find the elements that match the additional class names you want to match on as well.

Categories

Resources