0

I'm trying to login a website to web scrape its content with Selenium. The site has a virtual keyboard where the user inputs the password and I want to simulate the click on this keyboard.

https://www.rico.com.vc/

Inspecting the site, that's the part where the keyboard is generated (the position of each key is randomly generated by a JavaScript, but that part is OK):

<div class="password-buttons">
 <button class="button orange rounded" onclick="AddPsitions('8|9'); return false;" title="5 ou 3">
  <span class="login-number">5</span>
  <span class="login-or">ou</span>
  <span class="login-number">3</span>
 </button>
 <button class="button orange rounded" onclick="AddPsitions('6|7'); return false;" title="8 ou 2">
  <span class="login-number">8</span>
  <span class="login-or">ou</span>
  <span class="login-number">2</span>
 </button>
 <button class="button orange rounded" onclick="AddPsitions('4|5'); return false;" title="0 ou 6">
  <span class="login-number">0</span>
  <span class="login-or">ou</span>
  <span class="login-number">6</span>
 </button>

To simulate the click I'm doing the following (I also tried "//*[@title='0 ou 6']", without the '.'):

browser.find_element_by_xpath(".//*[@title='0 ou 6']").click()

But I'm getting this error:

Traceback (most recent call last):
 File "webScrape_Rico.py", line 59, in <module>
 browser.find_element_by_xpath(a).click()
 File "/home/luciano/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 293, in find_element_by_xpath
return self.find_element(by=By.XPATH, value=xpath)
File "/home/luciano/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 752, in find_element
'value': value})['value']
File "/home/luciano/.local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 236, in execute
self.error_handler.check_response(response)
File "/home/luciano/.local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 192, in check_response
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.InvalidSelectorException: Message: {" errorMessage":"Unable to locate an element with the xpath expression \".//*[@title='0 ou 6']\" because of the following error:\nError: TYPE_ERR: DOM XPath Exception 52","request":{"headers":{"Accept":"application/json","Accept-Encoding":"identity","Connection":"close","Content-Length":"109","Content-Type":"application/json;charset=UTF-8","Host":"127.0.0.1:60775","User-Agent":"Python-urllib/2.7"},"httpVersion":"1.1","method":"POST","post":"{\"using\": \"xpath\", \"sessionId\": \"8ddb4f90-f6e6-11e6-9eb0-4ba40f4453e7\", \"value\": \"\\\".//*[@title='0 ou 6']\\\"\"}","url":"/element","urlParsed":{"anchor":"","query":"","file":"element","directory":"/","path":"/element","relative":"/element","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/element","queryKey":{},"chunks":["element"]},"urlOriginal":"/session/8ddb4f90-f6e6-11e6-9eb0-4ba40f4453e7/element"}}

I saw this options here: Find and click element by title Python Selenium

What am I missing here?

3 Answers3

0

The XPath //button[@title='7 ou 8'] is working for me. You can use $x() to test XPaths in the Chrome browser, e.g. $x("//button[@title='7 ou 8']"). It will help you find the right locator faster.

JeffC
  • 22,180
  • 5
  • 32
  • 55
0

The title for those buttons is changing every time you open the site, so you can't use it to locate the buttons. I suggest you locate all the buttons using partial onclick attribute into list and use indexes to click on them

To make sure the elements are visible before clicking on them you can use explicit wait with expected_conditions

from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)
buttons = wait.until(EC.visibility_of_any_elements_located((By.XPATH, "//button[contains(@onclick, 'AddPsitions')]")))
buttons[0].click()
buttons[1].click()
#...
Guy
  • 46,488
  • 10
  • 44
  • 88
  • I'm treating this question about the buttons changing every time. Anyway, I tried your way and got this error: [...] selenium.common.exceptions.InvalidElementStateException: Message: {"errorMessage":"SyntaxError: DOM Exception 12" [...] – luciano araujo Feb 22 '17 at 01:16
  • But I tried a different approach: `buttons = browser.find_elements_by_xpath("//button[@class='button orange rounded']")` and I'm able to find the buttons but I got this error now: `selenium.common.exceptions.ElementNotVisibleException: Message: {"errorMessage":"Element is not currently visible and may not be manipulated"` Any thoughts on that? – luciano araujo Feb 22 '17 at 01:33
  • @lucianoaraujo Edited my answer. By the way, the xpath `"//button[@class='button orange rounded']"` doesn't find one of the buttons. – Guy Feb 22 '17 at 05:18
0

Solved!

I still not able to click the element by the title, but I found a workaround finding the element to click via its 'class', not 'title'.

browser.find_elements_by_xpath("//button[contains(@class, 'button orange rounded')]")

And then clicking the element with index:

a[click].click()

I was also having the following problem:

selenium.common.exceptions.ElementNotVisibleException: Message: {"errorMessage":"Element is not currently visible and may not be manipulated

And that was happening because I was not selecting the keyboard first. Since selenium literally simulates the user actions, I first have to select the virtual keyboard, so selenium can "see" the keys:

browser.find_element_by_id("txtPassword").click()

Thanks for all the help!