XPATH syntax for element in {} with Selenium for Python - python

I am currently trying to click each button on a webpage with Selenium in Python, the class and text is always the same for each button but each button has different ids. The ids, however, are within "data-paramaters" in {} and I can't figure out how to get the correct syntax for the xpath.
Here is a snippet of the website for one of the buttons:
<span class="contains-icon-details gc-btn gc-btn--s" data-isneededpromise="false" data-parameters="{"partner":"gs", "realId": "8da1d6a9-44d1-4556-bc12-92699749a30a", "tnId": "102086182829", "type": "details"}">More Details</span>
It seems the realId and the tnId are unique, so I would need to find the buttons with either one of those.
This works:
driver.find_element_by_xpath("//span[#class='contains-icon-details gc-btn gc-btn--s']").click()
but of course only for the first button as the class is always the same.
I tried something like this:
driver.find_element_by_xpath("//*[contains(#tnId, '102086182829')]").click()
but I get
Unable to locate element: //*[contains(#tnId, '102086182829')]
so definitely not the correct syntax.
I tried to find a solution online, but with no luck so far. Can anybody point me into the right direction? Thanks in advance.

In case realId value or tnId value is unique your XPath can be
driver.find_element_by_xpath("//*[contains(#data-parameters, '8da1d6a9-44d1-4556-bc12-92699749a30a')]").click()
or
driver.find_element_by_xpath("//*[contains(#data-parameters, '102086182829)]").click()

you should filter by the "data-parameters" attribute.
Try
driver.find_element_by_xpath("//span[contains(#data-parameters, '102086182829')]").click()
This is a dirty implementation of what you need. It would be better to extract the data-parameters field, deserialize JSON and check for the needed field;
spans = driver.find_element_by_xpath("//span[#class='contains-icon-details gc-btn gc-btn--s']")
for span in spans:
data_parameters = span.get_attribute("data-parameters")
try:
data_parameters = json.loads(data_parameters)
except:
continue
if 'tnId' in data_parameters and data_parameters['tnId'] == "102086182829":
span.click()
break

Related

interact elements with dynamic label in python selenium

Python newbie here. All of 1 month old. Most of the elements in page i am trying to scrape, i am able to handle them and interact with them. there are two elements that have dynamic labels which i am not able to handle. The source page looks as below
<span class="a-button-inner">
<input class="a-button-input" type="submit" aria-labelledby="Ae8MCi-55">
<span id="Ae8MCi-55" class="a-button-text" aria-hidden="true">Add Your Key</span>
</span>
Upon each refresh the label is new so i cannot get a fixed XPATH of that. There are multiple items with span class "a-button-inner" as well as input class "a-button-input" and there are other submit buttons as well in the rest of the page. The only thing unique is the Span text "Add Your Key".
Appreciate all help to get the submit button element and to click/submit it.
from selenium import webdriver
.
.
.
.
# objAddKey = driver.find_element_by_xpath('//*[#id="Ae8MCi-55"]/span/input') does not work as second round its a different XPath
objAddKey = driver.find_element_by_link_text('Add Your Key') # hoping this will get a sibling and then to get the parent and then look for all the children. I don't even know if its possible in python.
objAddKey.click()'
Tried to search for searching by span text, and came across some other stuff,
https://www.tutorialspoint.com/how-to-get-text-found-between-span-selenium
WebElement l = driver.findElement(By.xpath("//p/span"));
String s = l.getText();
but this does not help either.
https://selenium-python.readthedocs.io/locating-elements.html
went through this, but not much help either.
Appreciate your help and pointers.
Thank you.
If Add Your Key is unique then you can use the below xpath :
//span[contains(text(), 'Add Your Key')]//preceding-sibling::input[#class='a-button-input']
or even without class :
//span[contains(text(), 'Add Your Key')]//preceding-sibling::input
and use it like this :
objAddKey = driver.find_element_by_xpath("//span[contains(text(), 'Add Your Key')]//preceding-sibling::input")
objAddKey.click()
I would suggest you to have explicit waits for more reliability.
Selenium - Python - Explicit waits

Python Selenium Web-Driver not finding text element

I am trying to get the product's seller yet it will not get the text. I assume this is some weird thing since the text is also a link. Any help?
Python Code:
self.sold_by = driver.find_element_by_css_selector('#sellerProfileTriggerId').text
HTML Element:
SKUniverse
Try like this:
self.sold_by = driver.find_element_by_css_selector('#sellerProfileTriggerId')
text_element=self.sold_by.text
print(text_element)
Also, why aren't you using xpath or id selectors! Just asking :)

Yet another selenium question (driver.find_element_by_css_selector)

I'm trying to get string:
Liquidity (Including Fees)
from line
<div class="sc-bdVaJa KpMoH css-1ecm0so">Liquidity (Including Fees)</div>
I've tried these below
none of them gave me the string that I want:
usdbaslik = driver.find_element_by_css_selector("[class='sc-bdVaJa KpMoH css-1ecm0so']")
print(usdbaslik.text,":---text")
print(usdbaslik.tag_name,":---tag_name")
print(usdbaslik.id,":---id")
print(usdbaslik.size,":---size")
print(usdbaslik.rect,":---rect")
print(usdbaslik.location,":---location")
print(usdbaslik.location_once_scrolled_into_view,":---location_once_scrolled_into_view")
print(usdbaslik.parent,":---parent")
print(usdbaslik.screenshot_as_png,":--screenshot_as_png")
print(usdbaslik.screenshot_as_base64,":--screenshot_as_base64")
print(usdbaslik.__class__,":--__class__")
What am I doing wrong?
Thanks in advance.
There is (at least) one other element with that class on the page, so it's not a unique selector. The closest thing I was able to find to a unique selector looking at the page would be
usdbaslik = driver.find_elements_by_xpath('//div[#class="sc-VigVT fKQdIL"]//div[#class="sc-bdVaJa KpMoH css-1ecm0so"]')[0])
Then you can get the text from the label with
print(usdbaslik.get_attribute('innerText'))

Selenium find element by xpath not working

So to find a word in a certain page i decided to do this:
bodies = browser.find_elements_by_xpath('//*[self::span or self::strong or self::b or self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6 or self::p]')
for i in bodies:
bodytext = i.text
if "description" in bodytext or "Description" in bodytext:
print("found")
print(i.text)
I believe the code itself is fine, but ultimately I get nothing. To be honest I am not sure what is happening, it just seems like it doesn't work.
Here is an example of what website it would be ran on. Here is some of the page source:
<h2>product description</h2>
EDIT: It may be because the element is not in view, but I have tried to fix it with that in mind. Still, no luck.
Inspect the element and check if its inside the iframe,
if it does, you need switch to the frame first
driver.switch_to_frame(frame_id)
You could try waiting for a few ms to ensure the page has rendered and the expected element is visible with:
time.sleep(1)
Alternatively, try using IDs or custom data attributes to target the elements instead of xpath. Something like find_by_css_selector('.my_class') may work better.

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