Перейти к содержимому

Фотография

selenium.common.exceptions.StaleElementReferenceException:

selenium python parsing

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 3

#1 dima96

dima96

    Новый участник

  • Members
  • Pip
  • 2 сообщений
  • ФИО:Дмитрий Иванов

Отправлено 20 февраля 2019 - 18:15

Пытаюсь  написать парсер на питоне, используя селениум. Суть парсера в том, что нужно сначал повытаскивать url-адреса (их около 50 000). А потом уже парсить данные из каждой страницы.

Столкнулся с проблемой. Пытался выставлять тайминги до 10 секунд - не помогло. Самое интересное, что эта ошибка появляется постоянно в разных местах. По-моему, во всех случаях она была связана с выпадающим списком. Тут список довольно непростой. Вот его особенности.

1. Список открывается при наведении на него мышью.

2. Для того, чтобы получить url каждого пункта я навожу на него, кликаю на пункт меню, вытаскиваю url.

2.1. Каждый пункт списка состоит из подпунктов. Они видны (просто в зависимости от выбранного меню у них меняется id). Я  кликаю по ним, вытаскиваю url (без наведения), после чего навожу на список и перехожу к следующему пункту. И так цикл повторяется.

3. Изначльно список состоит из 6 пунктов (по дефолту в списке стоит значение Default). Но при клике на пункт меню он исчезает из списка и соответственно их там становится 5.

 

Вот мой код

    #Пункты из выпадающего меню
    a_list_text = []
    li_more = ul_nav.find_element_by_css_selector('li.r.more')
    ActionChains(driver).move_to_element(li_more).perform()
    a_more_list = li_more.find_elements_by_css_selector('div > div > p > a')
    
    #Добавляем пункты в список
    for a_more in a_more_list:
        a_list_text.append(a_more.text)

    #Проходим по пунктам
    for a in a_list_text:
        li_more = ul_nav.find_element_by_css_selector('li.r.more')
        ActionChains(driver).move_to_element(li_more).perform()
        #Создаём ещё один список с пунктами из меню
        a_more_list = li_more.find_elements_by_css_selector('div > div > p > a')

        for a_more_ in a_more_list:
            #Так как пункты в списке меняются местами, сверяем равен ли текущий пункт выбранному. Если да, запускаем цикл, если нет - переходим к следкющему
            if a == a_more_.text:
                a_more_.click()
                # time.sleep(2)
                print(driver.current_url)

                #Вытаскиваем подпункты
                more_sub_ul_nav = driver.find_element_by_css_selector("ul.sub-menu.subactive[style = 'display: block;']")
                more_sub_a_more_list = more_sub_ul_nav.find_elements_by_css_selector('li > a')
                
                #Проходим по подпунктам (они видны, без наведения)
                for more_sub_a_more in more_sub_a_more_list:
                    more_sub_a_more.click()
                    # time.sleep(2)
                    print(driver.current_url)

                #Когда прошли по все подпунктам - обрываем цикл и переходим к следующему пункту
                break
Traceback (most recent call last):
  File "all_links.py", line 90, in <module>
    count += parse(driver, 'https://****' + link_match.get("href"), count)
  File "all_links.py", line 48, in parse
    a_list_text.append(a_more.text)
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 76, in text
    return self._execute(Command.GET_ELEMENT_TEXT)['value']
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <a href=""> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed

В принципе, можно как-то try/except прикрутить, наверное. Я пробовал, но было 2 проблемы:

1. "Съедались" некоторые ссылки (видимо, неверно except настроил)

2. Всё-равно вылетала ошибка спустя какое-то время (видимо, неверно try вставил)

 

Уже который день пытаюсь побороть проблему - не получается. Может, кто-то что-то подскажет?.. Не знаю, куда ещё обратиться(

https://imgur.com/SUiVgiS

https://imgur.com/99Wqghy


  • 0

#2 checo

checo

    Опытный участник

  • Members
  • PipPipPipPip
  • 400 сообщений
  • Город:Н.Новгород

Отправлено 22 февраля 2019 - 13:14

Уверены, что Selenuim тут вообще нужен? Проще просто из исходника страницы всё получить. Или, если каждый раз список или адрес запрашивается, то отправлять такие же запросы и парсить. Модуль requests в помощь.


  • 0

#3 dima96

dima96

    Новый участник

  • Members
  • Pip
  • 2 сообщений
  • ФИО:Дмитрий Иванов

Отправлено 22 февраля 2019 - 18:17

Уверены, что Selenuim тут вообще нужен? Проще просто из исходника страницы всё получить. Или, если каждый раз список или адрес запрашивается, то отправлять такие же запросы и парсить. Модуль requests в помощь.

Уверен, можно было бы lxml или bs распарсить - распарсил бы. тут данные с js передаются, увы(


  • 0

#4 Likin

Likin

    Новый участник

  • Members
  • Pip
  • 1 сообщений
  • ФИО:Ликин Александр

Отправлено 07 мая 2019 - 18:39

Пытаюсь  написать парсер на питоне, используя селениум. Суть парсера в том, что нужно сначал повытаскивать url-адреса (их около 50 000). А потом уже парсить данные из каждой страницы.

Столкнулся с проблемой. Пытался выставлять тайминги до 10 секунд - не помогло. Самое интересное, что эта ошибка появляется постоянно в разных местах. По-моему, во всех случаях она была связана с выпадающим списком. Тут список довольно непростой. Вот его особенности.

1. Список открывается при наведении на него мышью.

2. Для того, чтобы получить url каждого пункта я навожу на него, кликаю на пункт меню, вытаскиваю url.

2.1. Каждый пункт списка состоит из подпунктов. Они видны (просто в зависимости от выбранного меню у них меняется id). Я  кликаю по ним, вытаскиваю url (без наведения), после чего навожу на список и перехожу к следующему пункту. И так цикл повторяется.

3. Изначльно список состоит из 6 пунктов (по дефолту в списке стоит значение Default). Но при клике на пункт меню он исчезает из списка и соответственно их там становится 5.

 

Вот мой код

    #Пункты из выпадающего меню
    a_list_text = []
    li_more = ul_nav.find_element_by_css_selector('li.r.more')
    ActionChains(driver).move_to_element(li_more).perform()
    a_more_list = li_more.find_elements_by_css_selector('div > div > p > a')
    
    #Добавляем пункты в список
    for a_more in a_more_list:
        a_list_text.append(a_more.text)

    #Проходим по пунктам
    for a in a_list_text:
        li_more = ul_nav.find_element_by_css_selector('li.r.more')
        ActionChains(driver).move_to_element(li_more).perform()
        #Создаём ещё один список с пунктами из меню
        a_more_list = li_more.find_elements_by_css_selector('div > div > p > a')

        for a_more_ in a_more_list:
            #Так как пункты в списке меняются местами, сверяем равен ли текущий пункт выбранному. Если да, запускаем цикл, если нет - переходим к следкющему
            if a == a_more_.text:
                a_more_.click()
                # time.sleep(2)
                print(driver.current_url)

                #Вытаскиваем подпункты
                more_sub_ul_nav = driver.find_element_by_css_selector("ul.sub-menu.subactive[style = 'display: block;']")
                more_sub_a_more_list = more_sub_ul_nav.find_elements_by_css_selector('li > a')
                
                #Проходим по подпунктам (они видны, без наведения)
                for more_sub_a_more in more_sub_a_more_list:
                    more_sub_a_more.click()
                    # time.sleep(2)
                    print(driver.current_url)

                #Когда прошли по все подпунктам - обрываем цикл и переходим к следующему пункту
                break
Traceback (most recent call last):
  File "all_links.py", line 90, in <module>
    count += parse(driver, 'https://****' + link_match.get("href"), count)
  File "all_links.py", line 48, in parse
    a_list_text.append(a_more.text)
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 76, in text
    return self._execute(Command.GET_ELEMENT_TEXT)['value']
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/home/m0nte-cr1st0/.local/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.StaleElementReferenceException: Message: The element reference of <a href=""> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed

В принципе, можно как-то try/except прикрутить, наверное. Я пробовал, но было 2 проблемы:

1. "Съедались" некоторые ссылки (видимо, неверно except настроил)

2. Всё-равно вылетала ошибка спустя какое-то время (видимо, неверно try вставил)

 

Уже который день пытаюсь побороть проблему - не получается. Может, кто-то что-то подскажет?.. Не знаю, куда ещё обратиться(

https://imgur.com/SUiVgiS

https://imgur.com/99Wqghy

 Ошибка связана с тем что страница обновилась, а у найденного элемента айдишник старый.
Решение перед использованием элемента искать его по новой.


  • 0



Темы с аналогичным тегами selenium, python, parsing

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных