【问题标题】:Dynamically generated element -NoSuchElementException: Message: no such element: Unable to locate element?动态生成的元素 -NoSuchElementException:消息:没有这样的元素:无法找到元素?
【发布时间】:2020-04-19 02:08:05
【问题描述】:

我无法在 Linkedin 页面上选择加载更多按钮。我在查找 xpath 时收到此错误:selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element

我怀疑问题在于当时该按钮在页面上不可见。所以我试过actions.move_to_element。但是,页面在元素下方滚动,因此该元素不再可见,并且随后会发生相同的错误。

我也尝试过move_to_element_with_offset,但这并没有改变页面滚动到的位置。

如何滚动到页面上的正确位置以便成功选择元素?

我的相关代码:

import parameters
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver

ChromeOptions = webdriver.ChromeOptions()
driver = webdriver.Chrome('C:\\Users\\Root\\Downloads\\chromedriver.exe')

driver.get('https://www.linkedin.com/login?fromSignIn=true&trk=guest_homepage-basic_nav-header-signin')
sleep(0.5)

username = driver.find_element_by_name('session_key')

username.send_keys(parameters.linkedin_username)
sleep(0.5)

password = driver.find_element_by_name('session_password')
password.send_keys(parameters.linkedin_password)
sleep(0.5)

sign_in_button = driver.find_element_by_xpath('//button[@class="btn__primary--large from__button--floating"]')
sign_in_button.click()

driver.get('https://www.linkedin.com/in/kate-yun-yi-wang-054977127/?originalSubdomain=hk')

loadmore_skills=driver.find_element_by_xpath('//button[@class="pv-profile-section__card-action-bar pv-skills-section__additional-skills artdeco-container-card-action-bar artdeco-button artdeco-button--tertiary artdeco-button--3 artdeco-button--fluid"]')

actions = ActionChains(driver)
actions.move_to_element(loadmore_skills).perform()
#actions.move_to_element_with_offset(loadmore_skills, 0, 0).perform()
loadmore_skills.click()

【问题讨论】:

    标签: python selenium


    【解决方案1】:

    在玩过它之后,我似乎已经弄清楚问题出在哪里。错误

    selenium.common.exceptions.NoSuchElementException:消息:没有这样的元素:无法找到元素:{"method":"xpath","selector":"//button[@class="pv-profile-section__card- action-bar pv-skills-section__additional-skills artdeco-container-card-action-bar artdeco-button artdeco-button--tertiary artdeco-button--3 artdeco-button--fluid"]"} (会话信息:chrome=81.0.4044.113)

    总是正确地说明它遇到的问题,因此它无法找到该元素。造成这种情况的可能原因包括:

    • 执行时元素不存在
    • 动态生成
    • 内容名称冲突

    就你而言,这是第二点。当您向下滚动时,显示的内容会动态加载。因此,当它首次加载您的个人资料时,技能部分实际上并不存在于 DOM 中。因此,要解决这个问题,您只需滚动到该部分,以便将其应用到 DOM 中。

    这一行就是这里的诀窍。它会将其定位到正确的面板,从而将数据加载并应用到 DOM。

    driver.execute_script("window.scrollTo(0, 1800)")
    

    这是我的代码(请根据需要更改)

    from time import sleep
    
    # import parameters
    from selenium.webdriver.common.action_chains import ActionChains
    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    
    ChromeOptions = webdriver.ChromeOptions()
    driver = webdriver.Chrome('../chromedriver.exe')
    
    driver.get('https://www.linkedin.com/login?fromSignIn=true&trk=guest_homepage-basic_nav-header-signin')
    sleep(0.5)
    
    username = driver.find_element_by_name('session_key')
    
    username.send_keys('')
    sleep(0.5)
    
    password = driver.find_element_by_name('session_password')
    password.send_keys('')
    sleep(0.5)
    
    sign_in_button = driver.find_element_by_xpath('//button[@class="btn__primary--large from__button--floating"]')
    sign_in_button.click()
    
    
    driver.get('https://www.linkedin.com/in/kate-yun-yi-wang-054977127/?originalSubdomain=hk')
    
    sleep(3)
    # driver.execute_script("window.scrollTo(0, 1800)")
    sleep(3)
    loadmore_skills=driver.find_element_by_xpath('//button[@class="pv-profile-section__card-action-bar pv-skills-section__additional-skills artdeco-container-card-action-bar artdeco-button artdeco-button--tertiary artdeco-button--3 artdeco-button--fluid"]')
    
    
    actions = ActionChains(driver)
    actions.move_to_element(loadmore_skills).perform()
    #actions.move_to_element_with_offset(loadmore_skills, 0, 0).perform()
    loadmore_skills.click()
    

    输出

    更新

    考虑到您的新问题,您需要实现一个连续滚动方法,使您能够动态更新skills 部分。这需要进行大量更改,理想情况下应该作为另一个问题提出。

    我还通过将滚动设置为正确的阈值找到了一个简单的解决方案。对于y=3200 似乎适用于我检查过的所有配置文件,包括您的、我的和其他一些配置文件。

    driver.execute_script("window.scrollTo(0, 3200)")
    

    【讨论】:

    • 感谢您的全面回答!如果技能部分位于不同 Linkedin 个人资料上的不同坐标,driver.execute_script("window.scrollTo(0, 1800)") 行会不再起作用吗?我的最终目标是创建一个在多个页面中运行的 for 循环,因此希望滚动无论 Linkedin url 都可以工作
    • 遗憾的是没有。在这种情况下,你可以做的是连续滚动直到找到元素。
    • 如果此答案有帮助,请随时接受答案:)。如果您确实难以实现连续滚动,请在此处提出另一个问题并@我。谢谢。
    • 有什么进展吗??如果你能给我一个更新,那就太好了。附带说明一下,如果您在最初的帖子中给出问题的整个背景,而不是逐步建立问题,那就太好了。
    • 感谢您的耐心等待。这条线工作driver.execute_script("window.scrollTo(0, 1800)"),但driver.execute_script("window.scrollTo(0, 3200)") 这条线没有,因为它为我滚动到页面的最底部。我将开始另一个问题,尝试实现一些连续滚动选项,但没有运气
    【解决方案2】:

    如果按钮在加载时在页面上不可见,则使用until 方法延迟执行

    try:
        myElem = WebDriverWait(browser, delay).until(EC.presence_of_element_located((By.ID, 'IdOfMyElement')))
        print "Button is rdy!"
    except TimeoutException:
        print "Loading took too much time!"
    

    示例取自here

    要获取元素的准确位置,可以使用以下方法。

    element = driver.find_element_by_id('some_id')
    element.location_once_scrolled_into_view
    

    这实际上是为了向您返回页面上元素的坐标(xy),但也会向下滚动到目标元素。然后,您可以使用坐标单击按钮。你可以阅读更多关于here的信息。

    【讨论】:

    • 感谢您的回复。我尝试了这两种解决方案均无济于事。我收到超时异常打印消息的第一个解决方案。第二个解决方案,我收到了同样的错误:NoSuchElementException: Message: no such element。我知道我的 xpath 是正确的,因为我已经在 ipython 中逐行使用它。
    • 非常微不足道的错误!!!发生这种情况是因为当您将其自动化时,它没有登录,因此通常会显示 LinkedIn 注册模式或链接配置文件的简短部分。尝试以隐身模式访问您的个人资料网址,您将看到上述任何一种情况。因此,它不包含skills section,因此会出现no element found 错误。
    • 啊,我应该在我的代码中包含它,但是是的,我已经登录了!为了简洁起见,我把它省略了。尽管已登录,但未找到该元素
    【解决方案3】:

    当我们在 selenium 程序代码中提到的定位器(即 id / xpath/name/class_name/css 选择器等)无法在网页上找到 web 元素时,您会收到 NoSuchElementException 错误。

    如何解决 NoSuchElementException:

    1. 应用 WebDriverWait : 允许 webdriver 等待特定时间
    2. 试试 catch 块

    因此,在对 webelement 执行操作之前,您需要查看 web 元素,我已经删除了 unwated 代码并避免使用硬编码等待,因为它不是处理同步问题的好习惯。此外,在单击显示更多按钮时,您必须向下滚动,否则它将不起作用。

    from selenium import webdriver
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.action_chains import ActionChains
    
    
    driver = webdriver.Chrome(executable_path="path of chromedriver.exe")
    
    driver.get('https://www.linkedin.com/login?fromSignIn=true&trk=guest_homepage-basic_nav-header-signin')
    driver.maximize_window()
    
    WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.NAME, "session_key"))).send_keys("email id")
    WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.NAME, "session_password"))).send_keys("password ")
    WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, "//button[@class='btn__primary--large from__button--floating']"))).click()
    
    driver.get("https://www.linkedin.com/in/kate-yun-yi-wang-054977127/?originalSubdomain=hk")
    driver.maximize_window()
    
    driver.execute_script("scroll(0, 250);")
    buttonClick = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, "//span[text()='Show more']")))
    ActionChains(driver).move_to_element(buttonClick).click().perform()
    

    输出:

    【讨论】:

      猜你喜欢
      • 2017-09-15
      • 1970-01-01
      • 1970-01-01
      • 2019-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-08
      相关资源
      最近更新 更多