Ошибка NoSuchElementException Unable to locate element при нажатии на кнопку в selenium
Всем добрый день. Пишу парсер Яндекс.Месенджера. Скрипт, переходя по этой ссылке https://yandex.ru/chat/#/ должен нажать на крестик в всплывающем окне:
крестик имеет класс
<div tabindex="-1" class="uik-icon-button uik-icon-button_hoverable">…</div>
И затем спарсить названия каналов не переходя по ним.
Ответы (1 шт):
Тут есть несколько проблем.
Загружаемая страница реализована используя javascript и основное содержимое загружается уже javascript-ом. Это объясняет то, что в html коде после загрузки не видно содержимого. Содержимое добавляется динамически.
Это приводит к целой серии проблем связанных с тем, что после почти каждого шага программы (например driver.get('https://yandex.ru/chat/#/')) в браузере запускается javascript реакция на этот шаг и эта реакция работает асинхронно c вашей программой. Это значит, что ваша программа после каждого шага должна синхронизироваться с тем, что происходит в браузере.
Обычно, это означает ждать, пока не закончится асинхронная операция. Так непосредственно после загрузки, т.е. после выполнения driver.get('https://yandex.ru/chat/#/') элемент, который программа пробует найти, еще не добавлен на страницу и программа должна подождать пока это случится, перед тем как она сможет на элемент, например, нажать.
Ожидание можно реализовать несколькими способами (см. например тут https://habr.com/ru/post/273089/).
Например, можно воспользоваться неявным ожиданием:
driver = webdriver.Chrome()
driver.implicitly_wait(10) # все операции будут ждать до 10 секунд
driver.get('https://yandex.ru/chat/#/')
Вторая проблема - всплывающее окно о файлах куки. Оно закрывает доступ к кнопке, и пока его не закрыть, кнопку нельзя нажимать (ни вручную ни из селениум).
Делается это приблизительно так:
wait = WebDriverWait(driver, 10)
btn = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '.lg-cc__button')))
btn.click()
Обратите внимание, здесь так же приходится ждать пока само окно не станет видимым, потому что окно с куки тоже загружается асинхронно.
Дальше, нужно чтобы программа дождалась, чтобы всплывающее окно о файлах куки полностью закрылось и не мешало нажать на кнопку. Закрытие окна тоже происходит асинхронно.
Я думаю принцип понятен - после каждого шага нужно ждать пока действие в браузере завершится.
Какое конкретно условие нужно ждать - зависит от страницы. Иногда, просто появление элемента в дереве DOM. Иногда, что он появился и видим. Иногда элемент бывает видим - но перекрыт другим полупрозрачным (как в случае с окном о файлах куки) и нужно дождаться когда станет доступен для нажатия.
Ну и еще одна более мелкая проблема - это неправильное использование функции find_element_by_css_selector. Она принимает один аргумент имя класса, передавать несколько имен через пробел - нельзя. Замените на driver.find_element_by_css_selector('.uik-icon-button.uik-icon-button_hoverable').