Селен: Ошибка Исключения Ссылки На Устаревший Элемент

#python-3.x #selenium

Вопрос:

Я пытаюсь просмотреть все страницы веб-сайта. но я получаю устаревшую ссылку на элемент: элемент не прикреплен к ошибке документа страницы. Это происходит, когда скрипт пытается перейти на третью страницу. Сценарий получил ошибку при запуске на страницу.нажмите(). Есть какие-нибудь предложения?

     while driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[-1].text=='...':
        links=driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')
        for link in links:
           if ((link.text !='...') and (link.text !='ADD DOCUMENTS')):
              print('Page Number: '  link.text)
              print('Page Position: ' str(links.index(link)))
              position=links.index(link)
              page=driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[position]
              page.click()
              time.sleep(5)
        driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[-1].click()
 

Комментарии:

1. Можете ли вы поделиться URL-адресом или источником HTML?

2. после вашего щелчка() DOM, вероятно, обновляется. Это приводит к тому, что каждый вызов метода после этого выбрасывает устаревший элемент. (Потому что ссылки, которые у вас есть, больше не действительны после обновления DOM.) В зависимости от ваших потребностей, вы можете просмотреть и получить ссылки. Затем используйте эти ссылки в цикле с помощью driver.get()s. На некоторых сайтах, которые могут не работать (если вы не можете добавлять ссылки в закладки…), поэтому вам придется сгладить.

Ответ №1:

Вы можете каждый раз находить элемент ссылки в соответствии с индексом, чтобы не использовать элементы, найденные изначально.
Что-то вроде этого:

 amount = len(driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a'))
for i in range(1,amount 1):
    link = driver.find_element_by_xpath("(//*[@id='jsGrid_vgAllCases']//a)[" str(i)  "]")
 

с этого момента вы можете продолжать в своем цикле for link вот так:

 amount = len(driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a'))
for i in range(1,amount 1):
    link = driver.find_element_by_xpath("(//*[@id='jsGrid_vgAllCases']//a)[" str(i)  "]")
        if ((link.text !='...') and (link.text !='ADD DOCUMENTS')):
            print('Page Number: '  link.text)
            print('Page Position: ' str(links.index(link)))
            position=links.index(link)
            page=driver.find_element_by_id('jsGrid_vgAllCases').find_elements_by_tag_name('a')[position]
            page.click()
            time.sleep(5)
 

(Я не уверен в правильности всего остального вашего кода, просто скопировал его и вставил)

Комментарии:

1. Я использую следующий код для перемещения ссылки, почему она не работает? страница=драйвер.идентификатор find_element_by_id(‘jsGrid_vgAllCases’).имя тега find_elements_by_tag_name(‘a’)[позиция]

2. Это действительно работает, он получает веб — элемент из списка, который вы собрали в начале, но так как вы перешли на другую страницу или страница была обновлена и т. Д. — Я понятия не имею, что именно там находится, — но страница была изменена, поэтому ранее полученные ссылки больше не указывали на эти элементы, так как элементы были изменены. В этом и заключается значение ошибки Устаревшего элемента. Вот почему вам нужно снова получить элементы, чтобы получить ссылку на существующий в данный момент элемент

Ответ №2:

У меня тоже возникла проблема с исключением Устаревшего элемента. Интересно, что с Firefox нет проблем, Chrome и Edge выходят из строя случайным образом. В общем, у меня есть два общих метода поиска с логикой повторных попыток, эти методы поиска будут выглядеть так:

      //  Yes C#  but should be relevant for any WebDriver...
     public static IWebElement( this IWebDriver driver, By locator)
     public static IWebElement( this IWebElement element, By locator)
 

Вариант веб-драйвера, похоже, отлично подходит для моих других запросов, так как поиск всегда «свежий»… Но поиск веб-элементов-это то, что вызывает горе. К сожалению, приложение вынуждает меня использовать версию WebElement. Почему его страница/html будет чем-то вроде:

     <node id='Best closest ID Possible'>
        <span>
            <div>text i want</div>
            <div>meh ignore this </div>
            <div>More text i want</div>
         </span>
         <span>
         <!-- same pattern ... --> 
 

Таким образом, код получает максимально близкий элемент по идентификатору и дочерним диапазонам, т. е. «//*[@id=’…’]/span» даст все узлы, представляющие интерес. Сейчас я сталкиваюсь с проблемами, перечисляя все элементы, я выполняю два выбора XPath, т. е. «./div[1]» и «./div[3]» для извлечения нужного текста. Это происходит только при извлечении текстовых узлов под элементами, где случайным образом будет брошен элемент StaleElement. Иногда самый первый XPath терпит неудачу, иногда я просматриваю несколько страниц, так как на страницах может быть 10 000 или более страниц, в то время как структура одинакова, я буду проверять случайные страницы, так как все они имеют одинаковый формат. Самое большее, я просмотрел 20 последовательных страниц с Chrome (версия 92.0.4515.107) или Edge (версия 94.0.986), оба, похоже, являются последними на данный момент.

Одно из решений, которое должно сработать, сначала получить все элементы span, т. Е. » //*[@id=’x’]/span», получить мой список, а затем запросить у драйвера, например:

     var nodeList = driver.FindElements(By.XPath('//*[@id='x']/span' ));

    for( int idx = 0 ; idx < nodeList.Count; idx  ) 
    {
    string str1 =  driver.FindElements(By.XPath("//*[@id='x']/span[idx 1]/div[1]")).GetAttribute("innerText");
    string str2 =  driver.FindElements(By.XPath("//*[@id='x']/span[idx 1]/div[3]")).GetAttribute("innerText");
    }
```

Think it would work but, YUK!  This is kind of simplified and being able to do an XPath from the respective "ID" located node would be preferable..