Цикл по списку webelements с селеном (python) для извлечения атрибута вызывает StaleElementReferenceException - PullRequest
0 голосов
/ 10 июля 2019

Я использую Selen Webdriver для поиска на веб-сайте, который дает мне несколько страниц с несколькими ссылками на каждой странице. Моя цель - создать список всех ссылок, произведенных поиском.

Он отлично работает для первой страницы, но когда я на второй странице, цикл for, где я пытаюсь извлечь атрибут 'href', создает исключение StaleElementReferenceException.

Я считаю, что должен быть какой-то способ исправить это с помощью WebDriverWait, но я не могу понять, как именно. Спасибо за любые предложения.

links =[]

while True:

  result = driver.find_element_by_id('results')
# list of all relevant elements on the page
  docs = result.find_elements_by_xpath('//li[@class="row1"]')

  for d in docs:
# this line produces StaleElementReferenceException
    link = d.find_element_by_tag_name('a')
    links.append(link.get_attribute('href'))

# try block checks if "next page" button exists and clicks it (this works fine)
  try:
    next_page = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, '//a[contains(@class,"la-TriangleRight")]')))
    driver.execute_script('arguments[0].click();', next_page)

# if "next page" button doesn't exist we break out of the loop
  except:
    break

EDIT: Сообщение об ошибке:

StaleElementReferenceException            Traceback (most recent call last)
<ipython-input-6-ad6166a696e6> in <module>
     23 #         link = WebDriverWait(d, 30).until(EC.presence_of_element_located((By.XPATH, '//a')))
     24         link = d.find_element_by_tag_name('a')
---> 25         links.append(link.get_attribute('href'))
     26 
     27 #     for i in range(25):

/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/selenium/webdriver/remote/webelement.py in get_attribute(self, name)
    139             attributeValue = self.parent.execute_script(
    140                 "return (%s).apply(null, arguments);" % getAttribute_js,
--> 141                 self, name)
    142         else:
    143             resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})

/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py in execute_script(self, script, *args)
    634         return self.execute(command, {
    635             'script': script,
--> 636             'args': converted_args})['value']
    637 
    638     def execute_async_script(self, script, *args):

/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/selenium/webdriver/remote/webdriver.py in execute(self, driver_command, params)
    319         response = self.command_executor.execute(driver_command, params)
    320         if response:
--> 321             self.error_handler.check_response(response)
    322             response['value'] = self._unwrap_value(
    323                 response.get('value', None))

/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/selenium/webdriver/remote/errorhandler.py in check_response(self, response)
    240                 alert_text = value['alert'].get('text')
    241             raise exception_class(message, screen, stacktrace, alert_text)
--> 242         raise exception_class(message, screen, stacktrace)
    243 
    244     def _value_or_default(self, obj, key, default):

StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  (Session info: chrome=75.0.3770.100)

Ответы [ 2 ]

0 голосов
/ 10 июля 2019

Вместо этого для каждого цикла, пожалуйста, используйте для цикла с диапазоном.

links =[]

while True:

  result = driver.find_element_by_id('results')
# list of all relevant elements on the page
  docs = result.find_elements_by_xpath('//li[@class="row1"]')

  for i in range(len(docs)):
# this line produces StaleElementReferenceException
    WebDriverWait(driver, 30).until(EC.staleness_of(docs[i]))
    link = docs[i].find_element_by_tag_name('a')
    links.append(link.get_attribute('href'))
    result = driver.find_element_by_id('results')
    docs = result.find_elements_by_xpath('//li[@class="row1"]')

# try block checks if "next page" button exists and clicks it (this works fine)
  try:
    next_page = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, '//a[contains(@class,"la-TriangleRight")]')))
    driver.execute_script('arguments[0].click();', next_page)

# if "next page" button doesn't exist we break out of the loop
  except:
    break
0 голосов
/ 10 июля 2019

StaleElementReferenceException появляется, когда элемент, с которым вы пытаетесь работать, больше не присутствует в html или устарел (обычно это происходит, когда страница обновилась после работы с элементом на странице).Итак, чтобы исправить это, вам нужно снова получить элементы.

В вашем случае вы можете исправить это следующим образом:

links =[]

while True:

  result = driver.find_element_by_id('results')
  docs = result.find_elements_by_xpath('//li[@class="row1"]')

  for d in docs:
    link = d.find_element_by_tag_name('a')
    links.append(link.get_attribute('href'))

  try:
    next_page = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, '//a[contains(@class,"la-TriangleRight")]')))
    driver.execute_script('arguments[0].click();', next_page)
    # Fetch the elements again here
    result = driver.find_element_by_id('results')
    docs = result.find_elements_by_xpath('//li[@class="row1"]')

  except:
    break
...