【问题标题】:How to locate an element on the webpage using Selenium and Python 3.6如何使用 Selenium 和 Python 3.6 在网页上定位元素
【发布时间】:2019-04-01 22:36:02
【问题描述】:

我正在尝试为 selenium 中的一个进程自动化准备 python 脚本。这是我第一次使用 xpath,但我不知道为什么这个 xpath 不起作用。

我从 chrome webinspect (F12) 获得它并单击文本框并复制为 xpath: '/html/body/div/form/div/div[5]/input[1]' 但 python 说程序找不到页面上有这样的 xpath,你能帮我解决这个问题吗?

我还认为可能是 python 试图检查这个太快,所以我试图延迟它直到页面被加载但它没有工作。

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]')

您能告诉我应该如何解决吗?

【问题讨论】:

  • 请说明你想要达到的结果。
  • @RKelley 请不要试图通过在表达式中撒上魔法仙尘来解决 XPath 问题,希望它能起作用。 “//”解决了你的问题并不意味着它解决了所有问题。
  • 我不认为在问题上作为 cmets 提出不正确的建议对任何人都有帮助,除非可能会发生一些非常奇怪的事情。在这种情况下,您的建议只是离题,表明缺乏研究。
  • 代码运行良好,但我不得不将 xpath 更改为不同的

标签: python-3.x selenium xpath css-selectors webdriverwait


【解决方案1】:

您所要做的就是等待用户名字段,然后与之交互。

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")

这是一般的 xpath 表示法。

//tag[@attribute='attribute_value']

如果你想指定更多属性,那么使用下面的。

//tag[@attribtue1='attribute_value1' and @attribute2 = 'attribute_value2']

【讨论】:

  • 嗨,谢谢你的帮助 - 我想我现在明白这个方法了,但是在执行你的代码时我得到了这个错误:userName = WebDriverWait(driver, 40).until(EC.presence_of_element_located(( By.XPATH, "//input[@name='USERNAME']"))) NameError: name 'By' is not defined
  • 你必须导入这个from selenium.webdriver.common.by import By。告诉我进展如何。
  • 我可以问你最后一个关于使用 For 循环的脚本的问题吗?当我尝试使用列表中的每个元素时,我在每个步骤中都有很多语法错误,例如 driver.get(url) 等 - 可以告诉我如何在循环中使用它来获取列表中的项目?
  • 当我尝试使用列表中的每个元素时,我在每个步骤的语法中都有很多错误,例如 driver.get(url) 等 - 可以告诉我如何在 Loop for item from 中使用它列表?
  • for element in elements: 然后在下一行处理你想对元素做什么。
【解决方案2】:

在我看来,Copy Xpath 菜单不是一个好工具。实际上,您应该避免使用 Xpath 定位器并仅将其用作最后的手段。您应该首先检查:

1) 如果元素有 id、name 或 className,那么它是理想的定位器,因此您可以直接访问该元素

2) 如果你可以使用 CSS 定位器

3) 只有这样你才应该使用 xpath 定位器。

xpath 是一个非常弱的定位器,好像明天前端开发人员更改网页并在用户名字段(您尝试访问的那个)上方放置一些标题,您找到的 Xpath “/html/body/div /form/div/div[5]/input[1]" 会改变,你的代码会中断。

现在,如果您使用直接访问您的元素:

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

name="用户名"

开发人员可以将输入移动到页面中的任何位置,您的测试仍然会找到该元素并且不会中断。

所以只需使用:driver.find_element_by_name("USERNAME");找到元素。

有更好的方法来做到这一点(页面对象模型),但现在你正在学习这种方式应该没问题。

祝你好运!

【讨论】:

  • 请注意,这是对使用 XPath 的特定风格的批评(特别是使用像 div/div[5]/input 这样的路径),而不是对 XPath 的一般批评。您需要找到一个在语义上反映您要查找的内容的 XPath,例如“页面上的第一个按钮”或“标有 SUBMIT 的按钮”,而不是页面上元素的精确坐标,因为那样太脆弱了.
【解决方案3】:

从您的代码试验/html/body/div/form/div/div[5]/input[1] 看来,您正试图将<input> 标记定位到文本为用户名 的元素。要将字符序列发送到所需字段,您需要诱导WebDriverWait以使所需元素可点击,您可以使用以下Locator Strategies

  • 使用CSS_SELECTOR

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

    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//input[@class='loginField loginFieldUser' and @name='USERNAME']"))).send_keys("mikzielinski")
    
  • 注意:您必须添加以下导入:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-14
    • 2021-05-03
    • 2020-05-29
    相关资源
    最近更新 更多