Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Selenium поиск и ожидание появления элемента на странице

webdriver
selenium
python
Теги: #<Tag:0x00007fedbaf516d0> #<Tag:0x00007fedbaf51540> #<Tag:0x00007fedbaf513d8>

(Максим Неверный) #1

Всем привет! Проблема в следующем - есть страница на ней должен появиться элемент через какое-то время, но обнаружить мы его можем только если введем его номер в поиск. Например: документ появится только тогда, когда система обработает все предыдущие данные (это может занять от 5 секунд до 5 минут), мы находим на странице поиск и вводим туда ID данного документа, и если он уже сформирован, то он отображается, если нет, то нет, соответственно. Стандартная операцияwait.until не прокатит в этом случае.

Я попытался организовать поиск и ожидание так:

e = driver.find_element_by_xpath("//*[text()[contains(.,'Ничего не найдено')]]")  
        while e is True:
            driver.find_element_by_name('query').send_keys(Keys.RETURN)
            time.sleep(2)

В итоге, скрипт доходя до данной точки падает с ошибкой:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[text()[contains(.,'Взять себе')]]"}

Selenium WD + Python


(Vasiliy Rakshin) #2

У вас в коде написано ‘Ничего не найдено’
а в сообщении об ошибке - ‘Взять себе’


#3

https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/support/ui/FluentWait.html


(Vasiliy Rakshin) #4

Саша, у топикстартера питон язык написания.


(елена бырканова) #5

e = driver.find_element_by_xpath("//*[text()[contains(.,‘Ничего не найдено’)]]") - сделать вместо поиска 1 одного элемента findElements. Тогда драйвер не будет падать, даже если ничего не найдет. Ну там дальше в цикле напишите обработку, как надо.


#6

Я уверен что Fluent есть и в питоне


(Максим Неверный) #7

Спасибо за ответы, но всё равно не очень понятно, в чем именно ошибка. Код ещё раз

        #####
        e = driver.find_element_by_xpath("//*[text()[contains(.,'Ничего не найдено')]]")
        while e is True:
            driver.find_element_by_name('query').send_keys(Keys.RETURN)
            time.sleep(2)
        driver.find_element_by_xpath("//*[text()[contains(.,'Взять себе')]]").click()

Как я это понимаю - пока драйвер находит элемент с текстом “Ничего не найдено” - искать по поиску некоторое значение, когда он что-то найдет, и “Ничего не найдено” больше не будет появляться на странице, то найти элемент с текстом “Взять себе” и кликнуть по нему. Вроде всё кажется простым и логичным, но всё равно падает с ошибкой.


selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//*[text()[contains(.,'Взять себе')]]"}

Такое ощущение, что while выполнился один раз и всё, но ведь условие заданное ранее e == True продолжает существовать.


(Vasiliy Rakshin) #8
  1. Возможно, надо заменить while e is True:
    на
    while driver.find_element_by_xpath("//*[text()[contains(.,‘Ничего не найдено’)]]") is True: ?
  2. Плохой вообще способ, мне видится, т.к. вы ожидаете Взять себе и каждый раз как 2 секунды её не видите - посылаете новый запрос на сервер… так вы её никогда не дождётесь если ответ от сервера будет идти более 2 секунд.

#9

Ошибка в том что если элемента нет в момент исполнения строчки

e = driver.find_element_by_xpath("//*[text()[contains(.,‘Ничего не найдено’)]]")
то ты получишь ексепшерн no such element.

Делай или как я написал чрезе FluentWait или как elena_byrkanova.
В случае с elena_burkanova тебе нужно заменить findElement на findElements ( не знаю как это в питоне), который возвращает список. И в цикле проверять длинну списка.

Вот алгоритм: Ищем элементЫ //*[text()[contains(.,‘Ничего не найдено’)]], если длинна списка 0 то засыпаем и ищем через 2 секунды а если длинна списка 1 то уже выполняем нужные дальше действия.


(Максим Неверный) #10
    • не помогло.
  • другого способа опроса страницы на присутствие этого элемента нет. Либо уже сформирован и находится через поиск, либо нет, и не находится. Просто ждём пока он появится.

(Максим Неверный) #11

FluentWait на Python нет.
И да, действительно опытным путём было выяснено, что просто не попадаю в цикл while. Самое интересное, что если перед циклом поставить просто найти элемент “Ничего не найдено” - всё Ок, находит, но если сразу же написать цикл, то проходит мимо:


        try:
            driver.find_elements_by_xpath("/TD[@class='no-results'][text()='Ничего не найдено.']")
            print(' Found')
        except:
            print(' Not found')
        time.sleep(2)

        while driver.find_elements_by_xpath("//*[text()[contains(.,'Ничего не найдено')]]") is True:
            print('While')
            driver.find_element_by_name('query').send_keys(Keys.RETURN)
            time.sleep(2)
        print('end While')

Ответ:


 Found
end While

Просто уже интересно, почему элемент на странице присутствует, но я не могу циклически подтверждать его существование?


(Vasiliy Rakshin) #12

Разные xpath, попробуйте с первым всё.


#13

Ставлю 10 гривен что в блок exception код никогда не зайдет.

find_elements возвращает список, длинна списка будет или 0 или 1 (если 1 элемент). Т.е не факт что оно нашло элемент, просто создался список.


(Максим Неверный) #14

Ок. В таком случае можете пояснить почему:
driver.find_element_by_xpath("//TD[@class='no-results'][text()='Ничего не найдено.']")
находит элемент, но:

while driver.find_element_by_xpath("//TD[@class='no-results'][text()='Ничего не найдено.']"):
...

стабильно падает, хотя строки идут одна за другой. Вы писали, что:

Но ведь мы видим, что элемент присутствует.


#15

Потому что в 1 строчке у тебя написано

driver.find_element!!!>>>>s<<<<!!!_by_xpath("/TD[@class=‘no-results’][text()=‘Ничего не найдено.’]") который никогда в жизни не упадёт, он не находит элемент а просто возвращает список элементов, пустой список. Элемента всё еще нет и он возвращает пустой список с длинной 0.

А следующая строчка уже идёт
driver.find_element_by_xpath("/TD[@class=‘no-results’][text()=‘Ничего не найдено.’]") (не elementS а element). Эта строчка уже конкретно возвращает Элемент, не список элементов а именно элемент. И если элемента не будет то мы получим ексепшен.

Итого:
driver.find_elementS - возвращает список, если элемента нет то вовращает пустой список с длинной 0.
driver.find_element - возвращает элемент и если элемента нет то мы получаем not found exception.


(Максим Неверный) #16

Спасибо большое за объяснение и терпение! Теперь всё заработало как надо! Сам я что-то тупил дико.


(Victor K) #17

Можно еще через try/catch exception сделать. Например написать
boolean flag = true;
while(flag){
try{
//метод
}catch(NosuchelementException ex){
flag = false;
}
}