How to use locate_with in selenium 4 - python

I'm trying to use relative locators in selenium 4, but I'm not having much luck with it.
I found an example here, but even though I'm able to find the first element, the second line doesn't work and it seems to be stuck there (I cannot close the browser automatically afterwards).
decision_div = browser.find_element(By.CLASS_NAME, "decisions")
conclusion_div = browser.find_element(locate_with(By.TAG_NAME, "div").below(decision_div))
How can I get it to find the next div right below the one with the specified class name?

As you are able to find the first element, I don't see any issues in your code as such:
decision_div = browser.find_element(By.CLASS_NAME, "decisions")
conclusion_div = browser.find_element(locate_with(By.TAG_NAME, "div").below(decision_div))
You just need to ensure that the the element with the value of class attribute as decisions is above the desired <div> element as follows:
<sometagname class="decisions" ...></div>
<div class="some class" ...></div>
Note : You have to add the following imports :
from selenium.webdriver.support.relative_locator import locate_with
References
You can find a couple of relevant detailed discussions in:
How to get the count of likes from a Twitter post using Selenium?

Selenium 4 relative locators are dealing with pair of web elements with the similar size and adjacent positions, not what you are trying to do here.
In this case the div element you are trying to locate is similarly nested below the parent element located by decisions class name.
So, you can simply locate the conclusion_div element with this code line:
conclusion_div = browser.find_element(By.XPATH, "//div[#class='decisions']//div")
But since the locator above gives 13 matches and I don't know which of them you want to locate it could be:
conclusion_div = browser.find_element(By.XPATH, "//div[#class='decisions']//div")
Or maybe
conclusion_div = browser.find_element(By.XPATH, "//*[#class='decisions']//div[contains(#class,'carousel')]")
Or maybe
conclusion_div = browser.find_element(By.XPATH, "//*[#class='decisions']//div[#class='decision-image']")

Related

Selenium Not Finding by ID, Class, or anything else... No iframes appear to be present

I've been looking through questions and answers like this one: Selenium Unable to Locate Element by ID
Most elements appear inaccessible by ID or XPATH. I'm attempting to find and click the element that has the text "Add Parent":
I've tried things like:
browser.find_element(By.XPATH, "/html/body/div/main/fs-person-page//iron-pages/fs-tree-person-details//div/section/fs-tree-person-family//fs-tree-collapsable-card/fs-family-members//div[2]/section[2]/div/button[2]/span/fs-inner-html")
and
browser.find_element(By.XPATH, "//fs-inner-html[text() = 'Add Parent']")
(similarly, finding by ids and classes doesn't seem to be working)
They solve the solution of not being able to find an element by switching to the iframe in which the element resides. The web page in which I'm searching for elements doesn't have any iframes. Do I need to be switching to something else? How can I determine what frame-like element I should be switching to?
Thanks!
Anson
The HTML of the webpage that I'm trying to scrape can be found here.
The issue with the
browser.find_element(By.XPATH, "//fs-inner-html[text() = 'Add Parent']")
xpath is that the text probably doesn't exactly equal 'Add Parent'.
There may be white-space on either side or the inside span 'to Maria Danko' is causing it to fail.
Just as a sanity check could you seen if any of these work?
button.add-person //css selector
button.add-person[data-test-add-parent=''] //css selector
//fs-inner-html[contains(text(), 'Add Parent')] //xpath

Unable to locate by element by class name using Selenium (Python)

I'm trying to locate a specific HTML element via class name but it's not finding anything. I've looked into it for a while but I'm unable to identify the issue
HTML snippet: div's class name is fl-l score
My Python Code:
# Throws Timeout Exception because element unable to be located.
WebDriverWait(self.driver, 5).until(ec.presence_of_element_located((By.CLASS_NAME, "fl-l score")))
score_block = self.driver.find_element_by_class_name("fl-l score")
I should also note that I tried finding it using XPath, which worked, but it's not a viable solution because the website is dynamic.
Instead of finding element by class name, you can change the locator by css selector for multiple class names:
WebDriverWait(self.driver, 5).until(ec.presence_of_element_located((By.CSS_SELECTOR, ".fl-l.score")))
score_block = self.driver.find_element_by_css_selector(".fl-l.score")
The above code hits the page twice, to be more efficient you should compress it into one line, like so:
score_block = WebDriverWait(self.driver, 5).until(ec.presence_of_element_located((By.CSS_SELECTOR, ".fl-l.score")))
In Selenium we do not have support for multiple class name, so basically we are left with only css and xpath in this kinda situation.
Since xpath is not viable solution in your case. try css.
You can combine multiple classes by removing the spaces in between, and simply putting . in that place.
Also, WebdriverWait will always return a common exception, and it's hard to figure out what exactly went wrong, so try using driver.find_element in case you want to have the proper error stack trace.
But for just that matter you should not remove WebdriverWait.
Try this :
score_block = self.driver.find_element_by_class_name("div.fl-l.score")
should work for you. if it works then replace with WebDriverWait

How to find an Element by index in selenium Webdriver for python

This is HTML code of that page
From there I want to access the 2nd element by using class name "maxbutton-1" as it has 3 same buttons and I can't use xpath or any constant selector so want to use the indexing with class and can't find anything to do that in python particular.
Also tried the method used in java to do same thing but it didn't worked.
Link of that same page
just trying to automate the movie downloading process for any movie.
Thank you.
To click on first, second or third button, try to change number of element:
el1 = driver.find_element_by_xpath("(//a[#class='maxbutton-1 maxbutton maxbutton-download-links'])[1]")
el2 = driver.find_element_by_xpath("(//a[#class='maxbutton-1 maxbutton maxbutton-download-links'])[2]")
el3 = driver.find_element_by_xpath("(//a[#class='maxbutton-1 maxbutton maxbutton-download-links'])[3]")
then you can extract element href/link attribute like that:
link = el.get_attribute('href')
or click it like that:
el.click()

Selenium not finding list of sections with classes?

I am attempting to get a list of games on
https://www.xbox.com/en-US/live/gold#gameswithgold
According to Firefox's dev console, it seems that I found the correct class: https://i.imgur.com/M6EpVDg.png
In fact, since there are 3 games, I am supposed to get a list of 3 objects with this code: https://pastebin.com/raw/PEDifvdX (the wait is so Seleium can load the page)
But in fact, Selenium says it does not exist: https://i.imgur.com/DqsIdk9.png
I do not get what I am doing wrong. I even tried css selectors like this
listOfGames = driver.find_element_by_css_selector("section.m-product-placement-item f-size-medium context-game gameDiv")
Still nothing. What am I doing wrong?
You are trying to get three different games so you need to give different element path or you can use some sort of loop like this one
i = 1
while i < 4:
link = f"//*[#id='ContentBlockList_11']/div[2]/section[{i}]/a/div/h3"
listGames = str(driver.find_element_by_xpath(link).text)
print(listGames)
i += 1
you can use this kind of loop in some places where there is slight different in xpath,css or class
in this way it will loop over web element one by one and get the list of game
as you are trying to get name I think so you need to put .text which will only get you the name nothing else
Another option with a selector that isn't looped over and changed-- also one that's less dependent on the page structure and a little easier to read:
//a[starts-with(#data-loc-link,'keyLinknowgame')]//h3
Here's sample code:
from selenium import webdriver
from selenium.common.exceptions import StaleElementReferenceException
driver = webdriver.Chrome()
url = f"https://www.xbox.com/en-US/live/gold#gameswithgold"
driver.get(url)
driver.implicitly_wait(10)
listOfGames = driver.find_elements_by_xpath("//a[starts-with(#data-loc-link,'keyLinknowgame')]//h3")
for game in listOfGames:
try:
print(game.text)
except StaleElementReferenceException:
pass
If you're after more than just the title, remove the //h3 selection:
//a[starts-with(#data-loc-link,'keyLinknowgame')]
And add whatever additional Xpath you want to narrow things down to the content/elements that you're after.

Selenium Find Sub-Child href Element

I'm trying to click the following link using selenium.
<div id="RECORD_2" class="search-results-item">
<a hasautosubmit="true" oncontextmenu="javascript:return IsAllowedRightClick(this);" class="smallV110" href="#;cacheurlFromRightClick=no"></a>
</div>
Which record to click is not known before the code is executed. Record_2 has multiple children, and the one included is the one I want to click. The link is edited for the sake of privacy. I tried to do something like that where name is the record variable, however it doesn't work.
driver.find_element_by_css_selector("css=div#"RECORD_%s" % (name).smallV110")
I'm a complete newbie to selenium so I couldn't figure out a way to sort this out. I would appreciate any help. Thanks!
Note that this is not Selenium IDE and you don't need the css= at the beginning of a selector.
There are multiple ways to locate the link element, e.g.:
driver.find_element_by_css_selector(".search-results-item a.smallV110")
driver.find_element_by_css_selector("[id^=RECORD] a.smallV110") # id starts with "RECORD"
If you know the id value beforehand:
id_i_know = 2
driver.find_element_by_css_selector("[id=RECORD_%d] a.smallV110" % id_i_know)
You don't have to have that smallV110 class attribute check - I've added it to increase chances of not matching other a elements inside the div (not sure what they are, you have not posted the entire HTML).

Categories