Reference to XPath - is it possible? - python

I am using Selenium to automate a browser task through a Python script.
There is a text-box in my browser that I need to fill with info, but the XPath is formatted as below:
//*[#id="NameInputId14514271346457986"]
The problem is that: everytime the number before the Id (14514271346457986) changes. Is there a way to refer to this XPath something like:
//*[#id.start-with="NameInputId"]
Sorry if it is a dumb question - I started to using Selenium this week and I couldn't find this info on documentation.

You can test whether the first 9 characters of the #id value equals "NameInput", for an XPath 1.0 expression:
//*[fn:substring(#id, 1, 9) = "NameInput"]
With XPath 2.0 (and greater) you could use the starts-with() function:
//*[starts-with(#id, "NameInput")]

Sure, you can use xpath like //*[contains(#id,"NameInputId")] but I guess this possibly will not be an unique locator. In this case the xpath should be more complex to contain additional attributes or some parent element

you can use xpath like this
//*[#id[contains(.,'NameInputId')]]

Related

I'm having trouble selectiong an element using Selenium with Python

I want to read out the text in this html element using selenium with python. I just can't find a way to find or select it without using the text (i don't want that because its content changes)
<div font-size="14px" color="text" class="sc-gtsrHT jFEWVt">0.101 ONE</div>
Do you have an idea how i could select it? The conventional ways listed in the documentation seem to not work for me. To be honest i'm not very good with html what doesn't make things any easier.
Thank you in advance
Try this :
element = browser.find_element_by_class_name('sc-gtsrHT jFEWVt').text
Or use a loop if you have several elements :
elements = browser.find_elements_by_class_name('sc-gtsrHT jFEWVt')
for e in elements:
print(e.text)
print(browser.find_element_by_xpath("//*[#class='sc-gtsrHT jFEWVt']").text)
You could simply grab it by class name. It's 2 class names so it would be like so. by_class_name only uses one.
If the class name isn't dynamic otherwise you'd have to right click and copy the xpath or find a unique identiftier.
Find by XPath as long as font size and color attribute are consistent. Be like,
//div[#font-size='14px' and #color='text' and starts-with(#class,'sc-')]
I guess the class name is random?

selenium exact match based on text

If I have some HTML:
<span class="select2-selection__rendered" id="select2-plotResults-container" role="textbox" aria-readonly="true" title="50">50</span>
And I want to find it using something like:
driver.find_element_by_xpath('//*[contains(text(), "50")]')
The problem is that there is 500 somewhere before on the webpage and it's picking up on that, is there way to search for a perfect match to 50?
Instead of contains, search for a specific text value:
driver.find_element_by_xpath('//*[text()="50"]')
And if you know it will be a span element, you can be a little more specific:
driver.find_element_by_xpath('//span[text()="50"]')
Note that your question asks how to find an element by its text value. If possible and would apply to your situation, you should look for a specific class or id, if known and consistent.
You can search for it by its absolute Xpath. For that, inspect the page and find the element. Then right-click it and copy its Xpath or full Xpath.
Otherwise you can use the id:
driver.find_element_by_id("select2-plotResults-container")
Here is more on locating elements.
use something like this
msg_box=driver.find_element_by_class_name('_3u328') and driver.find_element_by_xpath('//div[#data-tab = "{}"]'.format('1'))

How can I find the randomly Xpath using Selenium?

I am a newer in Selenium and use python to build it. Recently, I found a question which want to ask someone who can help me to figure it. The question is the Xpath I want to get is randomly, for example:
'//*[#id="wiki-edit-wikiEdit26"]/div/div/div/div[2]/a[1]'
'//*[#id="wiki-edit-wikiEdit27"]/div/div/div/div[2]/a[1]'
'//*[#id="wiki-edit-wikiEdit28"]/div/div/div/div[2]/a[1]'
These three xpath are used on the same button, but the number after wikiEdit will be changed every time. Therefore, are there any way which can help me to run my script more smoothly? Thank you very much!
Here is my python code:
broswer.find.element_by_xpath('//*[#id="wiki-edit-wikiEdit26"]/div/div/div/div[2]/a[1]') .click()
You can use matches in xpath to do this,
broswer.find.element_by_xpath("//*[matches(#id, '^(wiki-edit-wikiEdit)[0-9]')]/div/div/div/div[2]/a[1]") .click()
so basically that matches the id anything starting wiki-edit-wikiEdit followed by numbers form [0-9]
You just need to format your string..
import random
# Random range 1 - 100
x = random.randint(1,100)
broswer.find.element_by_xpath(f'//*[#id="wiki-edit-wikiEdit{x}"]/div/div/div/div[2]/a[1]') .click()
You can use starts-with or contains
broswer.find.element_by_xpath("//*[contains(#id,'wiki-edit-wikiEdit')]/div/div/div/div[2]/a[1]").click()
Also, using such long xpath's is not recommended. Use css-selectors over xpath.

Facebook post_box element. I cant find element by xpath

Facebook post_box element. I cant find element by xpath
Hi,
I learn to write automation test scripts in Selenium Webdriver with Python. I will make "Facebook Poster script". After login i wanna click in SendBox and sent some text, but i cant identyfing it with Xpath. Firebug not help mi with this. Thx for help.
Something like this:
After login
newpost=driver.find_element_by_xpath("i dont know correct xpath")
newpost.click()
newpost.send_keys("Hello!")
newpost.submit()
Xpath from Firebug not working
newpost = driver.find_element_by_xpath("/html/body/div[1]/div[2]/div[1]/div/div[2]/div[2]/div[2]/div/div[3]/div/div/div/div[2]/div[1]/div/div/div/div[2]/div/div[1]/div[1]/div[2]/div/div/div/div/div/div[2]/div/div/div/div")
First of all, never use absolute xpath - it's costly to maintain and looks just horrible.
As I understand, you need to click on input field with the placeholder 'what's on your mind'. Then you can get use of 'data-testid' attribute with value 'status-attachment-mentions-input'.
If you really need to use xpath, try this:
"//[#data-testid='status-attachment-mentions-input']". You can also use css selector and find yo element like this:
inputField = driver.find_element_by_css_selector("[data-testid='status-attachment-mentions-input']")
Correct solution:
newpost = driver.find_element_by_css_selector("[name='xhpc_message']")
newpost.click()
newpost.send_keys("Hello!")
newpost.submit()
#GVi thx for help

Parsing a wiki-styled web page, XPath error

I am new to XPath, and I totally fail to parse a simple wiki-styled web page with lxml.
I have a following expression:
"".join(tree.xpath('//*[#id="mw-content-text"]/div[1]/p//text()'))
It works fine, but I need to exclude children whose class is "reference" and get a lxml.etree.XPathEvalError with a following expression:
"".join(tree.xpath('//*[#id="mw-content-text"]/div[1]/p//*[not(#class="reference")].text()'))
What is the right XPath expression? Thanks in advance :)
Probably, the error occured because of .text() instead of /text().
If you want include also text of p elements then you have to use the descendant-or-self XPath axis:
//*[#id="mw-content-text"]/div[1]/p/descendant-or-self::*[not(#class="reference")]/text()

Categories

Resources