-1

I'm trying to prepare python script for one process automatization in selenium. It's my first time when I'm working with xpath and I don't have a clue why this xpath doesn't work.

I got it from chrome webinspect (F12) and clicked on textbox and copy as xpath: '/html/body/div/form/div/div[5]/input[1]' but python says that program cannot find such xpath on a page, could you help me with this?

I also thought that maybe python is trying to check this too fast so I tried to delay it until page will be loaded but it didn't worked.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common import by
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Firefox(executable_path='C:\webdrive\geckodriver.exe')

url= "https://b2b-sso.bmw.com/login/login_b2b.fcc? TYPE=33619969&REALMOID=06-88882215-3ed6-4d48-a202-c1198bb66e4d&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=$SM$fF%2fInZ1t%2b%2f1x7LPZ9ZpPr3Jmh3cKinaBuNkYKXWRFpXzW38w4hPWpxtCselZqile&TARGET=$SM$HTTPS%3a%2f%2fb2b%2ebmw%2ecom%2fgroup%2fb2b%3flang%3den"

driver.get(url)


try:
element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.xpath('//*[@id="mainContent"]/div[2]/ul/li[2]/a')))
)
finally:

us =     driver.find_element_by_xpath('/html/body/div/form/div/div[5]/input[1]')

Could you please advise me how should I resolve it?

DebanjanB
  • 118,661
  • 30
  • 168
  • 217
  • Please, clarify the result you want to achieve. – sentence Apr 01 '19 at 22:40
  • @RKelley please don't try solving XPath problems by sprinkling magic fairy dust into the expression in the hope that it works. The fact that "//" solved your problem doesn't mean it solves every problem. – Michael Kay Apr 02 '19 at 07:59
  • I don't think that making incorrect suggestions as comments on a question helps anybody, except possibly in cases where something really weird is going on. In this case your suggestion is just way off, and shows lack of research. – Michael Kay Apr 02 '19 at 17:34
  • Code is working fine, but I had to change xpath to different one – mikzielinski Apr 02 '19 at 21:29

3 Answers3

0

All you have to do is wait for user name field and then interact with that.

driver = webdriver.Firefox(executable_path='C:\webdrive\geckodriver.exe')

url= "https://b2b-sso.bmw.com/login/login_b2b.fcc? TYPE=33619969&REALMOID=06-88882215-3ed6-4d48-a202-c1198bb66e4d&GUID=&SMAUTHREASON=0&METHOD=GET&SMAGENTNAME=$SM$fF%2fInZ1t%2b%2f1x7LPZ9ZpPr3Jmh3cKinaBuNkYKXWRFpXzW38w4hPWpxtCselZqile&TARGET=$SM$HTTPS%3a%2f%2fb2b%2ebmw%2ecom%2fgroup%2fb2b%3flang%3den"

driver.get(url)
userName = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//input[@name='USERNAME']")))
userName.send_keys("hello")

And here is the general xpath notation.

//tag[@attribute='attribute_value']

if you want to specify more attributes, then use the below.

//tag[@attribtue1='attribute_value1' and @attribute2 = 'attribute_value2']
supputuri
  • 12,238
  • 2
  • 14
  • 34
  • Hi, thank for your help - I think that I understand this method now, but while executing your code I got this error: userName = WebDriverWait(driver, 40).until(EC.presence_of_element_located((By.XPATH, "//input[@name='USERNAME']"))) NameError: name 'By' is not defined – mikzielinski Apr 01 '19 at 23:18
  • you have to import this `from selenium.webdriver.common.by import By`. Let me know how it goes. – supputuri Apr 01 '19 at 23:21
  • May i ask you one last question regarding of using this script with For loop? When im trying to use for each element from list I have lots of errors in syntax for each step like driver.get(url) etc - could tell me how can I use it in Loop for item from list? – mikzielinski Apr 02 '19 at 21:30
  • When im trying to use for each element from list I have lots of errors in syntax for each step like driver.get(url) etc - could tell me how can I use it in Loop for item from list? – mikzielinski Apr 02 '19 at 21:33
  • `for element in elements:` and then in next line handle what ever you want to do with the element. – supputuri Apr 02 '19 at 21:37
  • haha, I used before and it didn't because of comment line in my eclipse - when I removed I got Unicode error. So I wrote this line of code again and it runs. Thank you very much for help - I can use excel file as data-src since now :) – mikzielinski Apr 02 '19 at 22:27
0

The Copy Xpath menu is not a good tool in my opinion. Actually you should avoid using the Xpath locator and use it only as a last resort. You should first check:

1) If the element has a id, name or className it's the ideal locator so you have a direct access to the element

2) If you can you the CSS locator

3) Only then you should use the xpath locator.

The xpath is a very weak locator as if tomorrow the Front End developer changes the web page and puts some header above the username field (the one you are trying to access), the Xpath you found "/html/body/div/form/div/div[5]/input[1]" will change and your code will break.

Now if you use a direct access to your element:

<input onkeypress="return Kernel.submitFormOnEnter(event)" tabindex="1" class="loginField loginFieldUser" name="USERNAME" size="13">

name="USERNAME"

The developer can move the input to anywhere in the page and your test will still find the element and won't break.

So just use: driver.find_element_by_name("USERNAME"); to find the element.

There are better ways to do this (Page Object Model), but for now since you are learning this way should be fine.

Good luck!

  • Note that this is a criticism of a particular style of using XPath (specifically, use of paths like `div/div[5]/input`) not a criticism of XPath in general. You need to find an XPath that semantically reflects what you are looking for, for example "the first button on the page", or "the button labelled SUBMIT", rather than the precise coordinates of the element on the page, because that's too fragile. – Michael Kay Apr 02 '19 at 08:03
0

From your code trials /html/body/div/form/div/div[5]/input[1] seems you are trying to locate the <input> tag adhusent to the element with text as Username. To send a character sequence to the desired field you need to need to induce WebDriverWait for the desired element to be clickable and you can use either of the following Locator Strategies:

  • Using CSS_SELECTOR:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "input.loginField.loginFieldUser[name='USERNAME']"))).send_keys("mikzielinski")
    
  • Using XPATH:

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='loginField loginFieldUser' and @name='USERNAME']"))).send_keys("mikzielinski")
    
  • 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
    
DebanjanB
  • 118,661
  • 30
  • 168
  • 217