Ошибка NoSuchElementException Unable to locate element при нажатии на кнопку в selenium

Всем добрый день. Пишу парсер Яндекс.Месенджера. Скрипт, переходя по этой ссылке https://yandex.ru/chat/#/ должен нажать на крестик в всплывающем окне:

крестик имеет класс

<div tabindex="-1" class="uik-icon-button uik-icon-button_hoverable">…</div>

И затем спарсить названия каналов не переходя по ним.


Ответы (1 шт):

Автор решения: Roman Konoval

Тут есть несколько проблем.

Загружаемая страница реализована используя 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').

→ Ссылка