I am trying to use Python and Selenium to click either Yes or No on these buttons:
The HTML for these buttons is as follows:
I've tried to select based on the XPath:
isbnButton = browser.find_elements_by_xpath("//a[#data-toggle='haveisbn'")
as suggested by a friend, but it's giving me an error that says the string is not a valid XPath expression. I know pretty much nothing about XPath and am doing a tutorial right now while I await answers, but I'm hoping someone can guide me in the right direction.
What I originally tried was:
dontHaveISBN = driver.find_elements_by_class_name('btn radio btn-radio btn-primary not-active w-100')
dontHaveISBN[1].click()
but that wasn't recognizing any elements.
How would you select and click on these buttons?
You can give it a try with xpath again (try to copy exactly the xpath from the source code):
dontHaveISBN=driver.find_element_by_xpath('xpath_here')
dontHaveISBN.click()
You can try with this code :
wait = WebDriverWait(driver, 10)
yes_button = wait.until(EC.element_to_be_clickable((By.LINK_TEXT, 'Yes')))
yes_button.click()
It's better to use Link Text than XPATH.
In case you want to use only xpath then that would be :
//a[text()='Yes']
Note that you will have to import these :
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
If you want to learn more about xpath then you can refer this link
Hope this will help.
In the xpath try you forgot the closing ], that's why it isn't valid. But there is a bigger issue with this locator: it matches the NO button as well.
In the class_name try you gave multiple classes as parameter, find_elements_by_class_name receives only one class as parameter.
data-id attribute seems to be unique, you can use it
# Yes button
driver.find_element_by_css_selector('[data-id="1"]')
# No button
driver.find_element_by_css_selector('[data-id="0"]')
# using xpath
driver.find_element_by_xpath('//a[#data-id="1"]')
Or using the text
driver.find_element_by_link_text('Yes')
driver.find_element_by_xpath('//a[text()="Yes"]')
Related
I am trying to extract a table from a webpage with python. I managed to get all the contents inside of that table, but since I am very new to webscrapping I don't know how to keep only the elements that I am looking for.
I know that I should look for this class in the code: <a class="_3BFvyrImF3et_ZF21Xd8SC", which specify the items in the table.
So how can I keep only those classes to then extract the title of them?
<a class="_3BFvyrImF3et_ZF21Xd8SC" title="r/Python" href="/r/Python/">r/Python</a>
<a class="_3BFvyrImF3et_ZF21Xd8SC" title="r/Java" href="/r/Java/">r/Java</a>
I miserably failed in writing a code for that. I don't know how I could extract only these classes, so any inputs will be highly appreciated.
To extract the value of title attributes you can use list comprehension and you can use either of the following locator strategies:
Using CSS_SELECTOR:
print([my_elem.get_attribute("title") for my_elem in driver.find_elements(By.CSS_SELECTOR, "a._3BFvyrImF3et_ZF21Xd8SC[title]")])
Using XPATH:
print([my_elem.get_attribute("title") for my_elem in driver.find_elements(By.XPATH, "//a[#class='_3BFvyrImF3et_ZF21Xd8SC' and #title]")])
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
Okay, I have made a very simple thing that worked.
Basically I pasted the code on VSCODE and the selected all the occurrences of that class. Then I just had to copy and paste in another file. Not sure why the shortcut CTRL + Shift + L did not work, but I have managed to get what I needed.
Select all occurrences of selected word in VSCode
I have a site that tracking all our shipment and i would like to use Selenium with Python to fetch all the value into my Excel file. But i'm currently stuck at getting Selenium to work. It will keep reporting back to me that the element is nowhere to be found. The element are also deep deep in the nested of DIV stuff.
at first i tried using
driver.find_element(By.XPATH,"//*[#id='trackItNowForm:j_idt529:0:j_idt535']").text
And quickly found out that part of the ID will constantly changing. (the "idt529:0:j_idt535" part in ID will constantly change to 519, 509 and so on. The zero path will also change based on lenght of data.) Without a clear structure. With that, By.ID is also obviously out of the window.
So now i'm currently out of idea on what to do next. Maybe i didn't put in the corrected syntax? I'm new to Selenium so i'm still confuse on a lot of things (like how XPATH are written and so on.) So an explanation will be appreciated.
You can locate that element by it's TrackingNumber class name. Maybe combined with more known attributes values.
Please try this:
driver.find_element(By.XPATH,"//label[contains(#id,'trackItNowForm') and(contains(#class,'TrackingNumber'))]").text
You may probably will need to add a delay to wait for the element to be visible. In this case WebDriverWait expected conditions is the right way to do it, as following:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(browser, 20)
wait.until(EC.visibility_of_element_located((By.XPATH, "//label[contains(#id,'trackItNowForm') and(contains(#class,'TrackingNumber'))]"))).text
You can try following css selector to identify the element.
option 1:
driver.find_element(By.CSS_SELECTOR,"[id^='trackItNowForm'][id*='id']").text
option 2:
driver.find_element(By.CSS_SELECTOR,"[id^='trackItNowForm'][id*='id'][class*='TrackingNumber']").text
where ^ means starts-with and * contains.
In option 1, it is checking id attribute starts-with trackItNowForm and also contains id
You should understand how xpath works.
For example, for the code you provided:
driver.find_element(By.XPATH,"//div[#class='col-sm-10']/label").text
looks for the first occurrence of a label under a div with the attribute class='col-sm-10' and then takes its text.
Useful links:
XPath syntax
XPath cheatsheet
I am very new to programing and am currently messing around trying to make a bot that will add items to my cart for me. I am using python with the selenium module. The problem I have came across is getting the program to find find an item using with src or href code.
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located(())
)
element.click()
This is the code I am using and I dont know what to put in the brackets to find the src or href. I am wondering which one is easier to use and how to use it in my code. Any advice/criticism at all could help me as I am still learning python. Thank you.
So your question is as follows:
[How] to find find an item using with src or href code[?]
Let's take a code snippet as an example.
This is from the https://www.google.com/ startpage. If you want to find this anchor element with said href attribute by specifically looking for the href url, you need to search with e.g.:
driver.find_element_by_xpath('//a[#href="https://mail.google.com/mail/?tab=rm&ogb"]')
Same goes for your code snippet:
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, ('//a[#href="https://mail.google.com/mail/?tab=rm&ogb"]'))))
element.click()
Imported modules:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
I'm trying to automate signing in on a page where there are two login buttons.
I'm still new with coding in general, but i read that xpath is the way to go.
browser.find_element_by_xpath("//input[#type='submit' and #value='Login']".click()
However, this defaults to the first login button. What selector should I use to select the second button?
This is the the code for the html:
Thanks
If the element more than one, you can use count [] at the end locator like this:
(//input[#type='submit' and #value='Login'])[2]
This is for second element:
browser.find_element_by_xpath("(//input[#type='submit' and #value='Login'])[2]").click()
Many ways you can do that.Since you are selecting last button.You can use index like (//input[#value='Login'])[last()]
Option 1:
browser.find_element_by_xpath("(//input[#value='Login'])[last()]").click()
Option 2
You can take the reference of table cell and xpath would be.
//td[#id='domainlogin_domain_selection']/following::td[1]/input[#value='Login']
So to click on the button.
browser.find_element_by_xpath("//td[#id='domainlogin_domain_selection']/following::td[1]/input[#value='Login']").click()
To handle dynamic element use WebDriverWait and element_to_be_clickable
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,"//td[#id='domainlogin_domain_selection']/following::td[1]/input[#value='Login']"))).click()
OR
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH,"(//input[#value='Login'])[last()]"))).click()
Note : You need to import followings when you use WebDriverWait.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
Consider using a css attribute = value selector with * contains operator to target the element by its onclick attribute. Nice and concise and easy to read
browser.find_element_by_css_selector("[onclick*=domainlogin]").click()
Reference:
Attribute selectors
Please try this code in order to click second login Button
browser.find_element_by_xpath("(//input[#value='Login'])[last()]").click()
or
browser.find_element_by_xpath("//td[#id='domainlogin_domain_selection']/following::td[1]/input[#value='Login']").click()
The buttons have different values of the onclick attribute so you can use the following selectors assuming using XPath contains() function:
First button:
//input[#type='submit' and #value='Login' and contains(#onclick, 'userLogin')]
Second button:
//input[#type='submit' and #value='Login' and contains(#onclick, 'domainLogin')]
References:
XPath Tutorial
XPath Axes
XPath Operators & Functions
What I'm dealing with
In one of my tests I need to interact with a pop-up input field that is very hard to select using a regular css selector or xpath. I know, however, that this pop-up box will have the focus.
How can I use the fact that it's focused to properly assert that the input field contains some text?
Pseudocode of what I'm looking for:
element = driver.find_element_by_FIND_THE_ELEMENT_WITH_FOCUS
assert elem.text == "foobar"
Partial solutions I've come across:
Possibly a working solution in Ruby:
element = #driver.find_element :css, 'input:focus'
sleep(3)
element.send_keys "Hello WebDriver!"
assert_equal(element.attribute('value'),"Hello WebDriver!")
Getting the focused element with jQuery:
var focus = $(document.activeElement);
Could you provide a solution in python please?
EDIT:
Here's the HTML of the element:
<div class="css-1492t68">Select a speaker...</div>
I realized my question could've lead to some confusion as the element itself is does not have the semantic <input> tag but is rather a <div>. I suppose this is handled by the quill-editor library, which our dev team used when designing this app.
Here's a screenshot of the pop-up box:
Since the element does not have a consistent CSS class, using an XPath expression is probably going to be your best bet.
You need to wait for the element to be clickable (which means intractable) by matching a <div> that contains the expected text, and has a CSS class that begins with css-. Doing this should allow enough time for JavaScript to do its thing in the browser to initialize the quill-editor and display it:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ExpectedConditions
xpath = "//div[starts-with(#class, 'css-')][contains(., 'The text you expect to find')]"
expected_condition = ExpectedConditions.element_to_be_clickable((By.XPATH, xpath))
element = WebDriverWait(driver, 20).until(expected_condition)
If this pop up field is directly inside a particular parent element, you can further limit your xpath expression accordingly.
If this succeeds, no error will be thrown. If it does not succeed, it should throw a WebDriverTimeoutException (or whatever this error is called in Python).
use:
elem = driver.switch_to.active_element