I am trying to get Selenium to do a Youtube search for me and I got to the final step which is actually entering the text and I'm stuck. searchElem uses the id that allows me to use .click(), but I cannot use send_keys() with that id so I tried inputElem and that doesn't work either.
There isn't a more specific id or class to use for the search input so I'm not sure what to do.
Below is the error I get once I try to use send_keys() with searchElem and inputElem.
selenium.common.exceptions.ElementNotInteractableException: Message: Element <div id="search-input" class="ytd-searchbox-spt"> is not reachable by keyboard
This is my code for the WebDriver and elements within the source code.
driver = webdriver.Firefox()
driver.get('https://www.youtube.com')
searchElem = driver.find_element_by_id('search-input')
inputElem = driver.find_element_by_id('search')
searchElem.click()
searchElem.send_keys('election')
It's possible that 'search' is the ID of a different element that is being picked up, so try using the xpath instead.
inputElem = browser.find_element_by_xpath('/html/body/ytd-app/div/div/ytd-masthead/div[3]/div[2]/ytd-searchbox/form/div/div[1]/input')
inputElem.send_keys('election')
You can create the locator based on search field placeholder (this would make it unique)
For example, for english, the placeholder would be "Search" and your locator would look like:
//input[#placeholder='Search']
Related
I'm playing around with booking.com as I teach myself selenium / python. I'm trying to select a currency based on a known string e.g. 'USD'.
I'm able to click the currency icon to open the currency selection modal but then when I try to say find element where text = 'USD', I get:
selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: An invalid or illegal selector was specified
1. Here is the list item for 'USD':
<li class="ccff2b4c43 ea27cffb06"><button data-testid="selection-item" type="button" class="fc63351294 ea925ef36a bf97d4018a ae8177da1f cddb75f1fd"><div class="a1b3f50dcd a1f3ecff04 b2fe1a41c3 db7f07f643 d19ba76520"><div class="b1e6dd8416 aacd9d0b0a"><span class="cf67405157">U.S. Dollar<div class=" ea1163d21f">USD</div></span></div><div class=""></div></div></button></li>
2. Here is my known string I'm trying to search for:
currency = 'USD'
3. Here is my attempt at trying to find (then select) this string in the HTML:
selected_currency_element = self.find_element(By.CSS_SELECTOR, f'//span[text()={currency}]')
selected_currency_element.click()
I assume I don't need to read this modal's entire unordered list into an array then loop through it to find the string? Or do I?
Couple of things to rectify.
The used syntax is for XPATH and you have used CSS_SELECTOR need to change to XPATH
selected_currency_element = self.find_element(By.XPATH, f'//span[text()={currency}]')
If you see the node USD is inside a DIV tag of parent SPAN
So your xpath should be like
selected_currency_element = self.find_element(By.XPATH, f'//span[.//div[text()="{currency}"]]')
Instead of using the abbreviation, I used the long name. This works pretty good. By the way, I use Firefox as my browser
from selenium.webdriver.common.by import By
from selenium import webdriver
def change_currenecy(country):
dvr = webdriver.Firefox()
dvr.get("https://www.booking.com/")
dvr.find_elements(By.XPATH, "//span[contains(text(),'USD')]")[0].click()
dvr.find_elements(By.XPATH, f"//span[contains(text(),'{country}')]")[0].click()
change_currenecy("Thai Baht")
You need to take care of a couple of things here:
Though you mentioed By.CSS_SELECTOR but the value is of a xpath. So you need to change the locator strategy as:
selected_currency_element = self.find_element(By.XPATH, f'xpath_value')
The desired text USD is within the descendant <div> of it's parent <span>, so you need to go a step deeper.
Solution
Your effective line of code will be:
currency = 'USD'
selected_currency_element = self.find_element(By.XPATH, f'//span//div[text()={currency}]')
selected_currency_element.click()
I'm using selenium in Python to try and scrape multiple pages. ID's and XPATH's keep changing per page, so I figured I'd best access them through their attribute-value combinations (see below).
I'm trying to access the text in the following element:
https://i.stack.imgur.com/ly1YU.png
which belongs to the following:
https://i.stack.imgur.com/strep.png
As I said, the ID's keep changing, so I wanted to access the element by data-fragment-name="articleDetail", or data-testid = "article-body". Can somebody help me how to do so?
Thanks in advance!
Try using the following CSS_SELECTOR
div[data-fragment-name='articleDetail'] div[data-testid='article-body']
Or XPath
//div[#data-fragment-name='articleDetail']//div[#data-testid='article-body']
The Selenium command can look like:
driver.find_element(By.CSS_SELECTOR, "div[data-fragment-name='articleDetail'] div[data-testid='article-body']")
Or
driver.find_element(By.XPATH, "//div[#data-fragment-name='articleDetail']//div[#data-testid='article-body']")
from selenium.webdriver.common.by import By
obj = driver.find_element(By.XPATH, "//div[#data-fragment-name='articleDetail']")
obj2 = driver.find_element(By.XPATH, "//div[#data-testid='article-body']")
where of course driver = webdriver.Firefox() or something like that and you already moved to the desired page.
Im trying to perform select and click action from the search box result dropdown for testing purpose. Though i dont get ant error but i'm stuck and not able to do so, search results came then disappeared immediately. Please any one help me out. Im using Python script to automate webdriver. Here is the screenshot below for reference.
. I have tried webdriverwait for same action but it gives Timeout exception error. If there is any child actions from CSS to perform let me know. Here is what i tried
search = driver.find_element_by_id('searchInput')
search.send_keys("flowers")
dropdown = WebDriverWait(driver, 4).until(
EC.presence_of_element_located((By.XPATH, "//li[text()='flowers']")))
Apart from this snippet, i want to rather just perform enter key operation, where i get query result for 'flower' on this ecomm. website.
Here is the website URL- https://paytmmall.com
Once you type flower in the input field, there are multiple options appearing based on the input provided. They are in li tags and under b tag.
Code :
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
#driver.implicitly_wait(30)
wait = WebDriverWait(driver, 30)
driver.get("https://paytmmall.com/")
search = wait.until(EC.visibility_of_element_located((By.ID, "searchInput")))
search.send_keys("flowers")
time.sleep(3)
wait.until(EC.visibility_of_element_located((By.XPATH, "(//li)[4]/descendant::b[contains(text(),'flowers')]"))).click()
time.sleep is just for visibility purpose. you can remove that as well.
Also this xpath (//li)[4]/descendant::b[contains(text(),'flowers')] is based on xpath indexing , since I think you wanna select the 4th option which is flower itself. In case you wanna select a different option, you would have to write the different xpath.
In case you are looking to just select the searched item, it's better to pass enter key once you type flower in the input field.
You can use the below code for that :
search = wait.until(EC.visibility_of_element_located((By.ID, "searchInput")))
search.send_keys("flowers")
time.sleep(3)
search.send_keys(Keys.RETURN)
The suggested options are not containing the text directly in li elements, they are inside child elements inside li elements.
Try this instead:
search = driver.find_element_by_id('searchInput')
search.send_keys("flowers")
dropdown = WebDriverWait(driver, 4).until(
EC.visibility_of_element_located((By.XPATH, "//li//*[text()='flowers']")))
#Thanks in advance for help. New to python, tried for hour trying to correct mistake.#
Trying to locate login button element. Attached is the image of the website with the element of the login button. please see here
Below is code:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
url = "https://www.xxxxxx.com/index.php/admin/index"
username = 'xxxx'
password = 'xxxxx'
driver = webdriver.Firefox(executable_path="C:\\Users\\kk\\AppData\\Local\\Programs\\Python\\Python38-32\\geckodriver.exe")
driver.get(url)
driver.find_element_by_name(name='aname').send_keys(username)
driver.find_element_by_name(name='apass').send_keys(password)
driver.find_elements_by_xpath('//style[#type="submit"]')
Rather than finding it with a CSS selector. Why not use find_element_by_xpath()
To get the XPath of that element just right-click the HTML of the input in Inspect Element, hover over Copy and you'll see "Full XPath"
Issue is your xpath.
driver.find_elements_by_xpath('//style[#type="submit"]')
Use below:
driver.find_elements_by_xpath('//input[#type="submit"]')
or
driver.find_elements_by_xpath('//input[#value="login"]')
#This is more accurate as many input tags could have type as submit
Also, please use some sort of wait as i am not sure if page will be loading fast enough every time you launch URL.
You can identify the submit button by using any of these 2:
//input[#type="submit"] or //input[#value="login"]
They should work without any problem if you don't have any similar elements on your page (which I doubt)
But if you want to be more precise, you can mix these 2 into:
//input[#value="login" and #type="submit"]
I am using selenium in python and cannot get it to find and select the ok button. Here is the code I am trying to use that is not finding the button.
SubmitElem = driver.find_element_by_name('ctl00$PlaceHolderMain$ctl01$RptControls$btnOK')
SubmitElem.submit()
And this is the webpage code
<input name="ctl00$PlaceHolderMain$ctl01$RptControls$btnOK"
value="OK"
onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$PlaceHolderMain$ctl01$RptControls$btnOK", "", true, "", "", false, false))"
id="ctl00_PlaceHolderMain_ctl01_RptControls_btnOK" accesskey="o"
class="ms-ButtonHeightWidth" type="submit">
Any advice on what I am doing wrong? I found some suggestions to add onclick*= but it did not seem to work.
As noted earlier, if the element is in an iframe, you need to switch contexts. Additionally, if the element takes time to show up on the DOM, due to it being dynamically rendered by JavaScript, you might need waits. You basically want to wait until the element shows up on the page before performing actions on it.
From the Selenium docs:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
Here is the Answer to your Question:
As per the HTML you have provided, you may consider the following options:
You can consider to construct a xpath based on name as follows:
SubmitElem = driver.find_element_by_xpath("//input[#name='ctl00$PlaceHolderMain$ctl01$RptControls$btnOK']")
SubmitElem.submit()
You can also try a different xpath based on id as follows:
SubmitElem = driver.find_element_by_xpath("//input[#id='ctl00_PlaceHolderMain_ctl01_RptControls_btnOK']")
SubmitElem.submit()
Alternatively, you can also consider to call click() method instead of submit() method.
SubmitElem.click()
Again, it seems to me that the id and name is dynamic due to presence of JavaScript and AJAX Calls. In that case you can consider to construct a dynamic xpath as follows:
SubmitElem = driver.find_element_by_xpath("//input[starts-with(#id, 'ctl00')]")
SubmitElem.submit()
You can consider to construct a dynamic css_selector as follows:
SubmitElem = driver.find_element_by_css_selector("input[id^='ctl00']")
SubmitElem.submit()
Finally, if you see a NoSuchElementException or ElementNotVisibleException you may consider to induce some WebDriverWait as follows:
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//input[starts-with(#name, 'ctl00')]")))
driver.find_element_by_css_selector("input[name^='ctl00']").click()
There are total 6 suggested locators to identify the element along with different other options.
Let me know if this Answers your Question.