Как можно исправить ошибку `StaleElementReferenceException` в библиотеке Selenium для Python?

Здравствуйте! У меня есть скрипт, который предназначен для парсинга названий карт. Если в названии карты содержится хотя бы один английский символ, скрипт переходит к этой карте, чтобы извлечь информацию об авторе, включая ссылку на профиль автора и Discord (если он доступен). Затем создается экземпляр класса MapMaker, который добавляется в множество mapmakers. Однако, если в названии карты английских символов нет, скрипт все равно проверяет имя автора на наличие английских символов. Если они присутствуют, создается экземпляр класса MapMaker и он также добавляется в множество mapmakers, после чего скрипт возвращается на страницу с картами. 

Тем не менее, при выполнении возникает ошибка `selenium.common.exceptions.StaleElementReferenceException: Message: stale element not found`. Как можно решить эту проблему? 

Код: 
<pre><code>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:
    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(By.XPATH, '//*[@id="app"]/div/main/div/div/d...
  • 19 ноября 2024 г. 17:23
Ответы на вопрос 2
Ошибка `StaleElementReferenceException` возникает, когда вы пытаетесь взаимодействовать с элементом, который больше не находится в DOM (Document Object Model) или был обновлён. В случае вашего скрипта это может происходить, когда вы кликаете на элемент карты и переходите на другую страницу, а затем пытаетесь использовать ранее найденные элементы (например, `maps_names`).

Чтобы исправить эту проблему, вам нужно обновлять ваш набор элементов после каждого перехода на новую страницу. Вот несколько способов исправления:

1. **Повторное получение элементов после клика**: После того как вы кликнули по элементу и перешли на новую страницу, повторно получите все нужные элементы. 

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

Вот пример того, как можно изменить ваш код:

```python
required_letters = 'qwertyuiopasdfghjklzxcvbnm'

mapmakers = set()

# Изначально загружаем карты
def load_maps():
    return driver.find_elements(By.CLASS_NAME, 'title')

maps_names = load_maps()
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

i = 0
while i < len(maps_names):
    map_name = maps_names[i]
    if any(letter in map_name.text.lower() for letter in required_letters):  # Проверяем наличие английских букв
        map_name.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(By.XPATH, '//*[@id="app"]/div/main/div/div/d...')

            # Создаваем экземпляр класса
            mapmaker = MapMaker(author_name.text, social_media.get_attribute("href"), profile_link.get_attribute("href"))
            mapmakers.add(mapmaker)

        except StaleElementReferenceException:
            print("Страница изменилась, перезагружаем карты.")
            maps_names = load_maps()  # Перезагружаем список элементов
            continue  # Возвращаемся к началу цикла и пробуем снова

        # Переходим назад к списку карт
        driver.back()
        maps_names = load_maps()  # Обновляем список карт после возврата
    i += 1
```

### Ключевые изменения:
- Создана функция `load_maps`, которая отвечает за получение текущего списка карт.
- После каждого клика (и после возврата) список карт обновляется. Это позволяет избежать `StaleElementReferenceException` при взаимодействии с элементами, которые уже не существуют в DOM.
- Упрощена логика проверки наличия букв в названии карты с помощью `any`.

Помимо этого, убедитесь, что у вас достаточно времени для загрузки страницы после клика, возможно, придется использовать `WebDriverWait`, чтобы дождаться элементов (например, после нажатия на кнопку "Назад", прежде чем заново загружать карты).
появляется ошибка selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: stale element not found. Как от нее избавиться?

Ошибка возникает тогда, когда ранее полученный элемент - устарел (изменен, удален итп).

Understanding Stale Element Reference Exception in... (на java внимание не обращаем, там главное суть понять).
Похожие вопросы