Динамически генерируемый элемент -NoSuchElementException: Сообщение: нет такого элемента: Невозможно найти элемент? - PullRequest
2 голосов
/ 19 апреля 2020

У меня проблемы с выбором кнопки «загрузить еще» на странице 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()

Ответы [ 3 ]

1 голос
/ 21 апреля 2020

Поэкспериментировав с этим, я, кажется, понял, откуда возникла проблема. Ошибка

selenium.common.exceptions.NoSuchElementException: Сообщение: нет такого элемента: невозможно найти элемент: {"method": "xpath", "selector": "// button [@class = "pv-profile-section__card-action-bar pv-skill-section__additional-skill artdeco-container-card-action-bar artdeco-button artdeco-button - третичная artdeco-button - 3 artdeco-button - жидкость"] "} (Информация о сеансе: 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()

Вывод

enter image description here

Обновление

В связи с вашей новой проблемой вам необходимо реализовать метод непрерывной прокрутки, который бы позволял вам динамически обновить раздел skills. Это требует больших изменений и в идеале должно быть задано как еще один вопрос.

Я также нашел простое решение, установив прокрутку на правильный порог. Для y=3200, кажется, отлично работает для всех профилей, которые я проверял, включая ваш, мой и некоторые другие.

driver.execute_script("window.scrollTo(0, 3200)")
0 голосов
/ 22 апреля 2020

Вы получаете ошибку NoSuchElementException, когда локаторы (т. Е. Id / xpath / name / class_name / css selectors et c), о которых мы упоминали в программном коде селена, не могут найти веб-элемент на веб-странице.

Как разрешить исключение NoSuchElementException:

  1. Apply WebDriverWait: разрешить веб-драйверу ждать определенного c времени
  2. Попробуйте блок перехвата

, поэтому перед выполнением действия над webelement вам нужно рассмотреть веб-элемент, я удалил неотредактированный код и также избегал использования жестко закодированных ожиданий, так как это не очень хорошая практика для решения проблемы синхронизации. Также, нажимая на кнопку Показать больше, вы должны прокрутить вниз, иначе она не будет работать.

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

Вывод:

enter image description here

0 голосов
/ 19 апреля 2020

Если кнопка не видна на странице во время загрузки, используйте метод 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!"

Пример взят из здесь

Чтобы получить точное местоположение элемента, вы можете использовать следующий метод для этого:

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

Это фактически намеревается вернуть вам координаты (x, y) из элемент на странице, но также прокрутите вниз вправо до целевого элемента. Затем вы можете использовать координаты, чтобы нажать на кнопку. Вы можете прочитать больше об этом здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...