Как можно решить проблему с исключением selenium.common.exceptions.StaleElementReferenceException в Python?

Здравствуйте! У меня есть скрипт, который парсит названия карт. Если в названии карты присутствует английский символ, он переходит на страницу этой карты, извлекает информацию об авторе, ссылки на его профиль и Discord (если имеется), затем создает экземпляр класса MapMaker и добавляет его в множество mapmakers. Если же в названии карты английских символов нет, скрипт проверяет, есть ли такие символы в имени автора, и, если находит, создает экземпляр класса MapMaker и добавляет его в множество mapmakers, после чего возвращается на страницу с картами. Однако возникает ошибка `selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: stale element not found`. Как можно избавиться от этой ошибки? <br/> <br/> Код: <br/> <pre><code class="python">required_letters = 'qwertyuiopasdfghjklzxcvbnm'

maps_names = driver.find_elements(By.CLASS_NAME, 'title')
print(len(maps_names))


class MapMaker:
    def __init__(self, username, social_media_link, link_to_profile):
        self.username = username
        self.social_media_link = social_media_link
        self.link_to_profile = link_to_profile


mapmakers = set()


i = 0
for map_name in maps_names:
    print(maps_names[i].text)
    for required_letter in required_letters:
        for letter in maps_names[i].text:
            if letter == required_letter:
                maps_names[i].click()
                try:
                    author_name = driver.find_element(By.XPATH, '//*[@id="app"]/div/main/div/div/div/div[1]/div[1]/dl/dd[1]/div/a/span')
                    profile_link = driver.find_element(By.XPATH, '//*[@id="app"]/div/main/div/div/div/div[1]/div[1]/dl/dd[1]/div/a')
                    social_media = driver.find_element(
  • 19 ноября 2024 г. 16:53
Ответы на вопрос 1
Для решения проблемы с `StaleElementReferenceException` в вашем коде, можно воспользоваться несколькими подходами. Эта ошибка возникает, когда вы пытаетесь взаимодействовать с элементом, который больше не существует в DOM (Document Object Model) или был обновлён. Вот несколько способов, как можно устранить эту ошибку:

1. **Повторное получение элемента**: Если вы вновь переходите на страницу или после взаимодействия с элементом, получайте элементы заново, чтобы гарантировать, что они актуальны.

2. **Индексация по названию карты**: Вместо сохранения списка `maps_names` в начале цикла, можно использовать `driver.find_elements` внутри цикла, чтобы всегда получать актуальные элементы.

3. **Использование явных ожиданий (Explicit Waits)**: Подождите, пока элемент снова не станет доступным перед тем, как пытаться с ним работать.

Вот пример кода с учётом указанных выше рекомендаций:

```python
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

required_letters = 'qwertyuiopasdfghjklzxcvbnm'

class MapMaker:
    def __init__(self, username, social_media_link, link_to_profile):
        self.username = username
        self.social_media_link = social_media_link
        self.link_to_profile = link_to_profile

mapmakers = set()

while True:  # Это нужно для постоянного выполнения, как пример
    # Получаем актуальные элементы
    maps_names = driver.find_elements(By.CLASS_NAME, 'title')
    
    for map_name in maps_names:
        map_text = map_name.text
        print(map_text)
        
        if any(letter in map_text for letter in required_letters):  # Проверка на наличие английских символов
            map_name.click()
            try:
                # Явное ожидание для элементов, чтобы дождаться их загрузки
                author_name = WebDriverWait(driver, 10).until(
                    EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/div/main/div/div/div/div[1]/div[1]/dl/dd[1]/div/a/span'))
                )
                profile_link = driver.find_element(By.XPATH, '//*[@id="app"]/div/main/div/div/div/div[1]/div[1]/dl/dd[1]/div/a')
                social_media = driver.find_elements(By.XPATH, '//*[contains(@class, "social-media")]')  # Пример, вы должны уточнить

                # Создание экземпляра класса MapMaker
                mapmaker = MapMaker(author_name.text, social_media[0].get_attribute('href') if social_media else None, profile_link.get_attribute('href'))
                mapmakers.add(mapmaker)

            except Exception as e:
                print(f"Ошибка при извлечении данных: {e}")

            # Возвращение к списку карт
            driver.back()
        else:
            # Если в названии карты нет английских символов, проверяем автора
            # Повторное получение актуальных элементов
            maps_names = driver.find_elements(By.CLASS_NAME, 'title')  # Обновляем список
            author_name_element = maps_names[i].find_element(By.XPATH, '..//..//..//div[1]/div[1]/dl/dd[1]/div/a/span')
            if any(letter in author_name_element.text for letter in required_letters):
                mapmaker = MapMaker(author_name_element.text, None, None)
                mapmakers.add(mapmaker)
```

С учётом этих изменений, ваш код будет более устойчив к `StaleElementReferenceException`. Проверьте, чтобы все XPATH и вспомогательные элементы соответствовали вашей структуре DOM.
Похожие вопросы