In a previous question
a user provides the following solution to the problem.
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='title
login_title' and text()='Login']//following::div[1]//input[#class='text header_login_text_box
ignore_interaction']"))).send_keys("someemail#email.com")
However, when I go into my chrome inspect element, I get the following XPATH by going copy>XPATH, which when added like the following, no longer works. It also doesn't give an error, just no email is typed into the box.
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='__w2_wHsckeIm21_email']"))).send_keys("someemail#email.com")
What's the difference between the two? Why does only the first one work and how do I obtain this long working version of xpath.
Well, not a concrete solution as such but do try out ChroPath Plugin.
Also available on Chrome Web Store.
https://autonomiq.io/chropath/
First of all you don't need such a long xpath to locate the email element. Simply you can use
//form[#class='inline_login_form']//input[#name='email']
And I don't recommend using id to identify in this case as it's dynamic (meaning the id will change each time you navigate to this page). So it's not a good idea to use the id to locate the element.
There are multiple ways to write locator for this element like
//form[#class='inline_login_form']//input[#name='email']
//input[#name='email'][#class='text header_login_text_box ignore_interaction']
//input[#name='email'][starts-with(#class,'text header_login_text_box')]
I don't want to keep on giving all the possible options. The idea I chosen the //form[#class='inline_login_form']//input[#name='email'] is, it's clear that I am locating the input element with name email under form. If you try to locate the element with only //input[#name='email'], then there are 2 elements and Selenium will pick the first element (which we don't want this case) and it's not intractable.
If you want to learn more about xpath and how to develop the correct xpath for your target element refer to this post
I suspect the id is not a stable selector for Quora.
When I try to repeat your steps today I find the XPath is slightly different, because the ID of the input field is different.
Today: //*[#id="__w2_wtEXFdHr21_email"]
In your example: //*[#id='__w2_wHsckeIm21_email']
XPath is loosely speaking a description of how you navigate the DOM to get to the element(s) of interest. There are many ways to get to a particular element. Chrome's dev tools will give you one way (or two if you count "Copy full XPath").
The question you linked has several answers that suggest different XPath expressions, and also CSS selectors. The ones looking for an input with name = email will find more than one element, where the input you're looking for is not the first.
Related
I am trying to scrape a website using selenium. My goal is to give an input string like "youtube" and my script will go ahead and click the links in that website that contain that string or similar strings. To elaborate on that, if the input string is "youtube" but the link has a friendly name "Youtube" or "You.tube" or "Youtube Go", I want the script to select/click it.
I have tried to use
driver.find_element_by_link_text("youtube").click()
but it gives error for links that are not an exact match (its also case sensitive so even if the link is "Youtube" it will give error)
driver.find_element_by_partial_link_text("youtube").click()
but this also gives error and the only difference with the first option is if I provide a shorter input than the link name and even then, the shorter input needs to be an exact match with a part of the link name.
Any advice is much appreciated!
You can use either of the following Locator Strategies:
Using xpath and contains(translate()) v1:
element = driver.find_element_by_xpath("//*[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'youtube')]")
Using xpath and contains(translate()) v2:
element = driver.find_element_by_xpath("//*[contains(translate('youtube','abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')]")
The first thing I notice here is that you want to go through all matching links found in a page, so I'll help you do that correctly first.
The find_element_by_partial_link_text() method will only return the first link that is found to match your search term. Instead, you can store the results of the find_elements_by_partial_link_text() method in a list. Selenium Documentation on locating elements can be found here
For example:
links = []
for link in driver.find_elements_by_partial_link_text("Youtube"):
links.append(link) # This will append the object itself
# To append the actual link:
# links.append(link.get_attribute('href'))
Code Source
Now, onto your main question. How can you find all links with similar partial text? From what I can gather, this isn't possible with Selenium by default. You'd have to iterate through all the possible variations of your term (eg. using string.lower(), string.upper() and other various methods to maximise the results returned) and run the find_elements code each time.
Another option would be to rewrite the method in the Selenium package to check the lowercase version of the link text it has found against the argument you pass it. Personally, I can't come up with any other strategies but I'm only an intermediate programmer, and have only used Selenium a couple of times. Hopefully someone will come along with a much better answer to do exactly what you want, however I hope the information I have provided will be of some use for now.
How can I find the log in button element? My script as below but not working after input username & password. Or shall I use find element by css selector or other? and how?
driver.find_element_by_name("username").send_keys(username)
driver.find_element_by_name("password").send_keys(password)
driver.find_element_by_class_name("cux-button ng-scope").click()
enter image description here
I assume that you are using Selenium and the Selenium Python bindings. (Tipp: Mention the library, you are using, in your question. :) )
The find_element_by_class_name() method only allows searching for a single class name, as already discussed in this question. As mentioned in the answers to that question, you can use the find_element_by_xpath() or find_element_by_css_selector() methods for more complex queries.
In your scenario, CSS selectors are sufficiently powerfull, so let's use them:
driver.find_element_by_css_selector(".cux-button.ng-scope").click()
For understanding CSS selectors, you might want to take a look into this tutorial by Sauce Labs, as recommended by the unofficial Python Selenium docs.
I am trying to find the textbox element using the find_element_by_xpath() method, but It keeps telling me it cant find said element, here's the line of code that does that.
I've tried finding it by link_text, partial link text, selector and it just doesn't work
bar = nav.find_element_by_xpath('//*[#id="react-root"]/div/div/div[2]/main/div/div/div/div[2]/div/div/aside/div[2]/div[2]/div/div/div/div/div[1]/div/div/div/div[2]/div/div/div/div')
Thanks in advance!
So, I suggest creating your xpath if you want to be precise and avoid taking it based on html structure (which can change).
The locators looks like:
And you can take it with xpath:
//input[#placeholder='Search people' and #role='combobox']
To avoid this problem, I suggest going trough a tutorial for a better understanding regarding how to create custom locators: Xpath tutorial
What was happening is: When I opened the tab to inspect the element, the DM structure changed because of my screen size so the xpath wasn't the same
So i was just trying to see if i could automate myself logging into the nike website when i realised that the xpath they use for the input changes every time you reload the page.
The only way i managed to find the element was by searching for it by the tag name input . However, when i then try to send the keys to it it gives me the error saying "element not visible". My question is how would i send the keys to it or is there a way of finding the xpath of an element each time i run the code by finding the element by the tag name (input)
Here is a copy of my code:
driver.get("https://www.nike.com/gb/en_gb/p/activity/login")
time.sleep(3)
driver.find_element_by_tag_name("input").send_keys("test")
And the website of the form is :https://www.nike.com/gb/en_gb/p/activity/login
Thanks in advance guys :)
I am able to set the email and password with below code
driver.find_element_by_xpath("//input[#type='email']").send_keys("abcd")
driver.find_element_by_xpath("//input[#type='password']").send_keys("abcd")
You can also use cssSelector to find elements:
driver.findElement(By.cssSelector("input[name='emailAddress']")).send_keys("abcd");
driver.findElement(By.cssSelector("input[name='password']")).send_keys("abcd");
Using css-selector is faster than xpath and, in my opinion, it's also easier to declare and customize.
I am new to this. I want to extract the xPath of an element and store it. Now I can find the element by its id or class name as they are unique.
Is there a way to extract the xPath of any element by identifying it thorough other attributes?
Thanks,
Adhiraj
You must first understand that there is no "the" with Xpath. Every object has many xpaths. So when you say you want to get "the xpath", you can understand that the question does not make sense.
Tools such as Firebug provide you with 'an' Xpath, presumably based on an algorithm which finds the first unique Xpath. Often this generated Xpath is complex, brittle and not suitable for automation