XPATH doesnt press a clickable button Python - python

my problem is that the first on is clicking and the second one doesnt and i dont undersatand why
WebDriverWait(rootdiv, 10).until(EC.element_to_be_clickable((By.XPATH, "//li[#onclick[contains(.,JTC)]]")))
rootdiv.find_element_by_xpath("//li[#onclick[contains(.,'JTC')]]").click()
WebDriverWait(depdiv, 10).until(EC.element_to_be_clickable((By.XPATH, "//li[#onclick[contains(.,AJU)]]")))
depdiv.find_element_by_xpath("//li[#onclick[contains(.,'AJU')]]").click()
depdiv and root div are children to look under for the certain li cause the root changes from the first to the second..
i've checked that the div is visible and in the first one, its clicking, the second time it cant find the object and im getting a time error
part of the code im trying to fed from..
<div class = "divCombo4">
<ul><li>....</li><ul>
<ul><li>...</li><ul>
</div>
and my depdiv is rooting to the find_element_by_id("divCombo4")
one of those ul li contains
onclick="selecionou('AJU', this,'.txtBusca4', 'false', 'destino', 'Estouem2', 'AJU');"

First of all, you need a dot to make the expressions context-specific. Also, the wait.until() returns a WebElement instance and you can use it instead of issuing a "find element" command again:
WebDriverWait(rootdiv, 10).until(EC.element_to_be_clickable((By.XPATH, ".//li[#onclick[contains(.,JTC)]]"))).click()
WebDriverWait(depdiv, 10).until(EC.element_to_be_clickable((By.XPATH, ".//li[#onclick[contains(.,AJU)]]"))).click()

Related

Selenium cannot find class [duplicate]

I'm trying to automate a process on this page, and according to its html code, after clicking the wallet button located at the top right corner of that page, it deploys 4 main wallets to choose to log in to the page.
All of those wallets share the same class which is elements__StyledListItem-sc-197zmwo-0 QbTKh, and I wrote the code below in order to try to get their button names (Metamask, Coinbase wallet...), here:
driver = webdriver.Chrome(service=s, options=opt) #execute the chromedriver.exe with the previous conditions
driver.implicitly_wait(10)
driver.get('https://opensea.io/') #go to the opensea main page.
WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//*[#id="__next"]/div/div[1]/nav/ul/div[2]/li/button'))) #wait for the wallet button to be enabled for clicking
wallet_button = driver.find_element(By.XPATH, '//*[#id="__next"]/div/div[1]/nav/ul/div[2]/li/button')
wallet_button.click() #click that wallet button
wallet_providers = driver.find_elements(By.CLASS_NAME, "elements__StyledListItem-sc-197zmwo-0 QbTKh") #get the list of wallet providers
for i in wallet_providers:
print(i)
After compiling the code above, I noticed that it didn't print anything, and it was due to the empty array of wallet_providers, which is very weird because I understand that by calling find_elements(By.CLASS_NAME, "the_class_name") it will then return an array containing the elements that share the same class, but it didn't do that in this case.
So, I would appreciate if someone could explain me what did I do wrong? In the end, I just wanted to manage to click on the Metamask button which doesn't always stay at the same location, sometimes it's the first element of that list, sometimes the second...
You are using this CLASS_NAME elements__StyledListItem-sc-197zmwo-0 QbTKh which has space in it.
In Selenium, a class name having space will not be parsed and will throw the error.
The reason why you did not get the error is cause you are using find_elements that will either return a list of web element or nothing.
So how to resolve this?
remove the space and put a . instead to make a CSS_SELECTOR
try this:
wallet_providers = driver.find_elements(By.CSS_SELECTOR, ".elements__StyledListItem-sc-197zmwo-0.QbTKh") #get the list of wallet providers
to be honest we can have better locator than this, cause it seems these values 197zmwo-0.QbTKh are generated dynamically.
I would rather use this CSS:
li[class^='elements__StyledListItem'] span[font-weight]
or this xpath:
//li[starts-with(#class,'elements__StyledListItem')]//descendant::span[#font-weight]
Also, you should print it like this: (this is one way but there are others as well):
Code:
driver.get("https://opensea.io/")
WebDriverWait(driver, 3).until(EC.element_to_be_clickable((By.XPATH, '//*[#id="__next"]/div/div[1]/nav/ul/div[2]/li/button'))) #wait for the wallet button to be enabled for clicking
wallet_button = driver.find_element(By.XPATH, '//*[#id="__next"]/div/div[1]/nav/ul/div[2]/li/button')
wallet_button.click() #click that wallet button
wallet_providers = driver.find_elements(By.CSS_SELECTOR, "li[class^='elements__StyledListItem'] span[font-weight]") #get the list of wallet providers
for i in wallet_providers:
print(i.get_attribute('innerText'))
Console output:
WalletConnect
MetaMask
Coinbase Wallet
Fortmatic
Process finished with exit code 0
The locators you are using are not relative enough, and on my first inspection, I somehow didn't locate them in the DOM. So, refactored code with relative locators to make the code work.
driver.get('https://opensea.io/') #go to the opensea main page.
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//*[#title='Wallet']"))).click()
wallets = WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.XPATH, "//*[#data-testid='WalletSidebar--body']//li")))
for wallet in wallets:
print(wallet.text)
Output:
WalletConnect
MetaMask
Popular
Coinbase Wallet
Fortmatic
Process finished with exit code 0
You use the class name elements__StyledListItem-sc-197zmwo-0 QbTKh which has space in it to find the elements. Actually, in Selenium we can't use the class name to locate an element/elements which have space in it. You can use CSS-Selector instead of the class name and in CSS-Selector you need to replace the spaces of the class with a (.) dot.
OR
You can use the parent class and then tags to point to the desired elements.
div[class='Blockreact__Block-sc-1xf18x6-0.eOSaGo'] > ul > li

I'm unable to locate the element to perform actions on it

I'm facing an issue locating the element on screen when there are no unique identifiers like ID, text etc. As it opens URL, I need to scroll down and click on button - 'Get Started' to proceed!...
Below is my code:
global driver
driver = webdriver.Chrome(ChromeDriverManager().install())
driver.maximize_window()
driver.get("https://My URL")
driver.implicitly_wait(10)
screen = driver.find_element(By.XPATH, '//div[#class="swiper-wrapper"]')
screen.click() (- This step doesnt through any error, i tried using this to scroll down the screen)
element = driver.find_element(By.XPATH, '//span[contains(text(),"Get Started")]')
driver.execute_script("arguments[0].scrollIntoView(true);", element )
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//span[contains(text(),"Get Started")]'))).click()
or
element.click()
Please help me in determining how to locate the element.
enter image description here
In this case you are trying to find span which is inside #shadow-root, Selenium won't be able to click elements inside #shadow-root in easy way. Look here: How to click button inside #shadow-root (closed) using Selenium and Python
But in your case you probably don't need/want to click this specific span, becouse you have custom element ion-button, which has some click event listener attached to it.
You can check XPATH value in browser devtools. If you go to Elements tab, you can right click desired element and choose option Copy>Copy Xpath. Also make sure your element is not inside iframe tag, it could cause problem as well.

Trying to click entry buttons on gleam using selenium but am having trouble identifying the element

Here is the inspect result for the button that says +5 per day
>span class="text user-links entry-method-title ng-scope ng-binding" ng-include="::'views/entry-text/'+entry_method.entry_type+'.html'">
Click For a Daily Bonus Entry"
</span>
<div class="entry-method bonus template" data-remove-popovers="" id="em6129519" ng-class="{expanded: entryState.expanded == entry_method, template: entry_method.template, 'completed-entry-method': !canEnter(entry_method) && isEntered(entry_method)}" ng-repeat="entry_method in ::entry_methods">
here is the HTML given information when I inspect the link/button, I have tried to use XPath, CSS, link text, and class name and it keeps giving me an error saying it cannot identify the element. Does anyone have a suggestion for how to identify this, it is on gleam.io for a giveaway I'm trying to automate this so i don't have to log in and press this everyday. This is my first ever web interfacing project with python.
Here is my most recent try
driver.maximize_window()
time.sleep(10)
driver.execute_script("window.scrollTo(0, 1440)")
time.sleep(10)
button2 = driver.find_element_by_class_name("text user-links entry-method-title ng-scope ng-binding")
button2.click()
Similar to a previous issue, Selenium find_element_by_class_name and find_element_by_css_selector not working, you can't have spaces in your class name when using driver.find_element_by_class_name. Instead, find the element via css_selector and replace each space with a dot.
driver.find_element_by_css_selector("span.text.user-links.entry-method-title.ng-scope.ng-binding")
That'll fix what you have above, but keep in mind there are other ways to make selenium actions more reliable (eg. WebDriverWait, etc). And there may be a cleaner selector to use than the one above.
I believe the element you want to access is contained within an "iframe", thus you must first switch to iframe before you can access it using selectors.
driver.switch_to.frame(x.find_element_by_xpath("PUT IFRAME XPATH HERE"))

How to get next page in silenium?

I am working on selenium in python, I want to scrape all pages, but I am in trouble:
Here is the element I want to click:
I am using the folloing code:
link=driver.find_element_by_link_text ('2')
link.click()
But it give click on another element
Deos there exist another way to get next page?
First of all, sees like your element what you're trying to click overlapped by another one, so you need to wait for its becoming being clickable or other one disappear:
el = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH,//div[#id="pagination_wrapper"]//li[#value="1"])))
or
WebDriverWait(driver, LONG_TIMEOUT
).until_not(EC.presence_of_element_located((By.XPATH,"//div[#class='close_cookie_alert']")))
Here's like you can find all of yours elements:
link1 = driver.find_element_by_xpath('//div[#id="pagination_wrapper"]//li[#value="1"]')
link2 = driver.find_element_by_xpath('//div[#id="pagination_wrapper"]//li[#class="2"]')
link3 = driver.find_element_by_xpath('//div[#id="pagination_wrapper"]//li[contains(text(),"text of the third element")]')
if usual click doesn't work, try to use click via javascript, like that:
driver.execute_script("arguments[0].click();", link1)
or, just move to the next page with:
driver.get('new_page')

How to use click() on more then one element with the same XPath?

In my project, I want to use click() on a list with buttons. They all have the same xpath. But when I run through the list I scraped with seleniums driver.find_elements_by_xpath(). I just click on the first one and then the for loop breaks.
Don't know if I approach it the wrong way.
Code:
driver.get(url)
try:
myElem = None
myElem = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//a[#href ='javascript:;']")))
if myElem != None:
buttons = driver.find_elements_by_xpath("//a[#href ='javascript:;']").click()
for button in buttons:
button.click()
HTML:
<a class="open" data-path="/public/employees/767772/description.json" href="javascript:;">
<span class="icon-caret-right"></span> 続きを読む
</a>
You can use List in selenium
List<WebElement> LIST = driver.findElements(By.xpath(""));
LIST.get(0).click();
first you need to store all clicks in list then if you want click first click you can do that with LIST.get(0).click();`
This line is your problem:
buttons = driver.find_elements_by_xpath("//a[#href ='javascript:;']").click()
You're doing find_elements but because of the click() at the end you're clicking on the first item then returning the response from the click() into buttons. That means buttons is not a list or array. I don't think anything returns from a click() so when you try to iterate through, you have nothing to iterate on.
Your code is mostly right If you drop the .click() on that line you will get a list and then you can iterate through:
buttons = driver.find_elements_by_xpath("//a[#href ='javascript:;']")
for button in buttons:
button.click()
This pretty much is the solution provided by #JustinLambert - but i think he's provided an example in the a different language.
In Python you don't need to worry about declaring it as a List<T> - just assign it to a variable as you already have done.

Categories