List not printing all .text values using Selenium and Python - python

So I've been using selenium recently and decided to pull some values into a list using the following:
Values = browser.find_elements_by_xpath("//div[#class='main-col']//li[#class='test-item test-item--favourites']")
The values are all stored as expected. Though when I use for example:
for i in range (len(Values)):
print(Values[i].text)
i+=1
The code runs up to about the 50th index in the list and outputs the details, but after this its blank. I can run:
print(values[50])
It will output but .text gives me nothing.
Im using pYcharm for the development and looked into the variables at this stage. I can see that once I click on the variable it states 'collecting variable data' and after this I can then output some more of the variables in the list.
Is there a way I can force selenium to collect all the variable data so I can loop through each index in the list and store it in the .text format or is there a better alternative/method I can use?

If the .text is blank that means that there is no text between CSS Selector. To get an attribute out of a CSS Selector you have to use the get_attribute() function. Inside the () you place a string which is the name of an attribute which value you are looking for. for example
print(i.get_attribute('class'))

You are able to extract the text till the 50th index as find_elements_by_xpath() was able to identify 50 odd elements as per your Locator Strategy.
Solution
To collect all the desired elements using Selenium and python you have to induce WebDriverWait for visibility_of_all_elements_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR and get_attribute("innerHTML"):
print([my_elem.get_attribute("innerHTML") for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "div.main-col li.test-item.test-item--favourites")))])
Using XPATH and text attribute:
print([my_elem.text for my_elem in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//div[#class='main-col']//li[#class='test-item test-item--favourites']")))])
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

Related

Copied xpath directly from chrome, and not working

Trying to scrape odds from fanduel, goal is to get the player's name. In this case Jayson Tatum.
https://sportsbook.fanduel.com/basketball/nba/philadelphia-76ers-#-boston-celtics-31137202?tab=player-points
Even when I copy the xpath directly from chrome it doesnt seem to work. Though it works when I hardcode and look for an element through xpath containing the text Jayson Tatum.
This is my code
name = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.XPATH,'//*[#id="root"]/div/div[2]/div[1]/div/div[2]/div[3]/div/div[2]/div/div[3]/div[1]/div/div/div[1]/span')))
Also tried this
name = driver.find_element(By.XPATH, '//*[#id="root"]/div/div[2]/div[1]/div/div[2]/div[3]/div/div[2]/div/div[3]/div[1]/div/div/div[1]/span')
Still get a NoSuchElement trying both ways.
To print the text Jayson Tatum you can use the following Locator Strategy:
Using xpath and text attribute:
print(driver.find_element(By.XPATH, "//span[text()='UNDER']//following::div[1]//span").text)
Ideally you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategy:
Using XPATH and get_attribute("innerHTML"):
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//span[text()='UNDER']//following::div[1]//span"))).get_attribute("innerHTML"))
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
You can find a relevant discussion in How to retrieve the text of a WebElement using Selenium - Python
References
Link to useful documentation:
get_attribute() method Gets the given attribute or property of the element.
text attribute returns The text of the element.
Difference between text and innerHTML using Selenium

How to get span value without class on python selenium

I'm new on python, just started learning, I try to get value span on other website and I'm trying to get value on this picture on red mark , but I still get an error.
Snapshot of the HTML:
To print the text 4 hours 30 minutes you can use either of the following Locator Strategies:
Using css_selector and get_attribute("innerHTML"):
print(driver.find_element(By.CSS_SELECTOR, "div.lab-preamble__details.subtitle-headline-1 > span").get_attribute("innerHTML"))
Using xpath and text attribute:
print(driver.find_element(By.XPATH, "//div[#class='lab-preamble__details subtitle-headline-1']/span").text)
Ideally you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR and text attribute:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.lab-preamble__details.subtitle-headline-1 > span"))).text)
Using XPATH and get_attribute("innerHTML"):
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[#class='lab-preamble__details subtitle-headline-1']/span"))).get_attribute("innerHTML"))
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
You can find a relevant discussion in How to retrieve the text of a WebElement using Selenium - Python
References
Link to useful documentation:
get_attribute() method Gets the given attribute or property of the element.
text attribute returns The text of the element.
Difference between text and innerHTML using Selenium
If you're using only selenium to find element you can try to get this element using find_element_by_xpath.
To get xpath fast and easy you can right-click element in Chrome DevTools and in "Copy" section there is the "Copy xpath" option.

Is there a way to get the value within a <div> using selenium in python?

I'm new to python and webscraping so I'm not sure what the name of the value inbetween the <div>'s in an element is called. Sorry for not being able to specify.
<div class="syllable">value</div>
Is there a way to have the value inbetween the <div>'s get assigned to a string variable in python using selenium using XPath?
For example, the "value" in the element would be a string and it would print out:
value
I'm new to python and selenium so I can't figure it out.
To print out the text of the element.
elem=driver.find_element_by_class_name("syllable")
print(elem.text)
xpath:
elem=driver.find_element_by_xpath("//div[#class='syllable']/text()")
print(elem)
it is called html innerText
you can retrieve this value using text in selenium , or get_attribute.
This returns the rendered text (means displayed text)
elem=driver.find_element_by_class_name("syllable")
print(elem.text)
This return the text with out checking the style attribute meaning returns value even if its not displayed in UI
elem=driver.find_element_by_class_name("syllable")
print(elem.get_attribute("textContent")
you can find elem using this text also:
// partial match
elem=driver.find_element_by_xpath("//div[contains(text(),'value')])
print(elem.text)
// exact match
elem=driver.find_element_by_xpath("//div[text()='value')])
print(elem.text)
// exact match of the elements text if there is any child element like span it won't return the element
elem=driver.find_element_by_xpath("//div[.='value')])
print(elem.text)
Also note:
Other things you could read about outerHTML , innerHTML
To print the text value you can use either of the following Locator Strategies:
Using class_name and get_attribute("textContent"):
print(driver.find_element_by_class_name("syllable").get_attribute("textContent"))
Using css_selector and get_attribute("innerHTML"):
print(driver.find_element_by_css_selector("div.syllable").get_attribute("innerHTML"))
Using xpath and text attribute:
print(driver.find_element_by_xpath("//div[#class='syllable']").text)
Ideally you need to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using CLASS_NAME and get_attribute("textContent"):
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CLASS_NAME, "syllable"))).get_attribute("textContent"))
Using CSS_SELECTOR and text attribute:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.syllable"))).text)
Using XPATH and get_attribute():
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//div[#class='syllable']"))).get_attribute("innerHTML"))
Console Output:
value
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
You can find a relevant discussion in How to retrieve the text of a WebElement using Selenium - Python
References
Link to useful documentation:
get_attribute() method Gets the given attribute or property of the element.
text attribute returns The text of the element.
Difference between text and innerHTML using Selenium

Capture Class Text - Selenium Python

I'm trying to capture an element of a web page using selenium in python
<span class="_2-1_O"><span dir="auto" class="_1jlxc _3Whw5">Ana Smith</span></span>
I'm trying to capture the name Ana Smith in Phyton:
nome_contato = driver.find_elements_by_class_name("_1jlxc _3Whw5").text
However, python cannot locate
try:
name= driver.find_elements_by_class_name("_1jlxc _3Whw5").text
except Exception as e:
print("|False")
Result: |False
.text does not need () it's just ".text"
In general it's easier to help with more information, but from the information you gave that's the main issue that I see.
find_elements_by_class_name returns a list, be careful. You can use find_element_by_class_name if you want the first element or you can select one element of the list returned by find_elements_by_class_name.
To handle dynamic element you need to induce WebDriverWait and wait for element to be visisble
visibility_of_element_located() and following css selector
Code:
print(WebDriverWait(driver,10).until(EC.visibility_of_element_located((By.CSS_SELECTOR,"._1jlxc._3Whw5"))).text)
you need to import following libraries
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
You have to consider a couple of things:
find_elements_by_* will return a list. But you want that particular element. So you have to use find_element_by_* instead.
driver.find_element_by_class_name() takes a single class. So it won't accept multiple classes as in:
driver.find_element_by_class_name("_1jlxc _3Whw5")
Most important, the element is a dynamic element, so to print the text Ana Smith you have to induce WebDriverWait for the visibility_of_element_located() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR and get_attribute("innerHTML"):
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "element_css"))).get_attribute("innerHTML"))
Using XPATH and text attribute:
print(WebDriverWait(driver, 20).until(EC.visibility_of_element_located((By.XPATH, "element_xpath"))).text)
However, the value(s) ofthe class attribute, _1jlxc, _3Whw5, etc indicates that the values are generated by either ReactJS, Vue.js, etc. So those values are never static and they would keep on changing everytime you access the webpage.
Solution
Apart from inducing WebDriverWait you have to construct either css-selectors or xpath based on static attributes possibly from some ancestor elements.

How to find element based on what its value ends with in Selenium?

I am dealing with a situation where every time I login a report is displayed in a table whose ID is dynamically generated with random text ending with "table".
I am automating this table with selenium python web driver. It has Syntax
driver.find_element_by_xpath('//*[#id="isc_43table"]/tbody/tr[1]/td[11]').click();
help me editing this syntax to match it with table ending id with "table".
(only one table is generated).
The ends-with XPath Constraint Function is part of XPath v2.0 but as per the current implementation Selenium supports XPath v1.0.
As per the HTML you have shared to identify the element you can use either of the Locator Strategies:
XPath using contains():
driver.find_element_by_xpath("//*[contains(#id,'table')]/tbody/tr[1]/td[11]").click();
Further, as you have mentioned that table whose ID is dynamically generated so to invoke click() on the desired element you need to induce WebDriverWait for the element to be clickable and you can use the following solution:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[contains(#id,'table')]/tbody/tr[1]/td[11]"))).click()
Alternatively, you can also use CssSelector as:
driver.find_element_by_css_selector("[id$='table']>tbody>tr>td:nth-of-type(11)").click();
Again, you can also use CssSelector inducing WebDriverWait as:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "[id$='table']>tbody>tr>td:nth-of-type(11)"))).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
I hope, either these 2 will work for you
driver.find_element_by_xpath("//table[ends-with(#id,'table')]/tbody/tr[1]/td[11]").click();
OR
driver.find_element_by_xpath("//table[substring(#id,'table')]/tbody/tr[1]/td[11]").click();
If not getting, remove the tags from tbody.
For such situations, when you face randomly generated ids, you can use the below functions with XPATH expression
1) Contains,
2) Starts-with &
3) Ends-with
4) substring
Syntax
//table[ends-with(#id,'table')]
//h4/a[contains(text(),'SAP M')]
//div[substring(#id,'table')]
You need to identify the element which is having that id, whether its div or input or table. I think its a table.
You can try below XPath to simulate ends-with() syntax:
'//table[substring(#id, string-length(#id) - string-length("table") +1) = "table"]//tr[1]/td[11]'
You can also use CSS selector:
'table[id$="table"] tr>td:nth-of-type(11)'

Categories