Python 如何解决循环槽元素时的StaleElementReferenceException(Selenium)

Python 如何解决循环槽元素时的StaleElementReferenceException(Selenium),python,selenium,for-loop,selenium-chromedriver,staleelementreferenceexception,Python,Selenium,For Loop,Selenium Chromedriver,Staleelementreferenceexception,我正试图从一个网站上搜集有关足球比赛的信息。因此,我使用Python中的Selenium库 我将所有需要匹配的可点击html元素存储在一个名为“completed_matches”的列表中。我创建了一个for循环,它通过所有这些可点击的html元素进行迭代。在循环中,我单击当前html元素并打印新的URL。代码如下所示: from selenium import webdriver import selenium from selenium.webdriver.support.ui import

我正试图从一个网站上搜集有关足球比赛的信息。因此,我使用Python中的Selenium库

我将所有需要匹配的可点击html元素存储在一个名为“completed_matches”的列表中。我创建了一个for循环,它通过所有这些可点击的html元素进行迭代。在循环中,我单击当前html元素并打印新的URL。代码如下所示:

from selenium import webdriver
import selenium
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome(r"C:\Users\Mart\Downloads\chromedriver_win32_2\chromedriver.exe")
url = "https://footystats.org/spain/la-liga/matches"
driver.get(url)
completed_matches = driver.find_elements_by_xpath("""//*[@id="matches-list"]/div[@class='full-matches-table mt2e ' or @class='full-matches-table mt1e ']/div/div[2]/table[@class='matches-table inactive-matches']/tbody/tr[*]/td[3]/a[1]/span""");
print(len(completed_matches))
for match in completed_matches:
        match.click()
        print("Current driver URL: " + driver.current_url)
159
Current driver URL: https://footystats.org/spain/fc-barcelona-vs-real-club-deportivo-mallorca-h2h-stats#632514
---------------------------------------------------------------------------
StaleElementReferenceException            Traceback (most recent call last)
<ipython-input-3-da5851d767a8> in <module>
      4 print(len(completed_matches))
      5 for match in completed_matches:
----> 6         match.click()
      7         print("Current driver URL: " + driver.current_url)

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py in click(self)
     78     def click(self):
     79         """Clicks the element."""
---> 80         self._execute(Command.CLICK_ELEMENT)
     81 
     82     def submit(self):

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py in _execute(self, command, params)
    631             params = {}
    632         params['id'] = self._id
--> 633         return self._parent.execute(command, params)
    634 
    635     def find_element(self, by=By.ID, value=None):

~\Anaconda3\lib\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))

~\Anaconda3\lib\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=79.0.3945.79)
  (Driver info: chromedriver=72.0.3626.7 (efcef9a3ecda02b2132af215116a03852d08b9cb),platform=Windows NT 10.0.18362 x86_64)
输出如下所示:

from selenium import webdriver
import selenium
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome(r"C:\Users\Mart\Downloads\chromedriver_win32_2\chromedriver.exe")
url = "https://footystats.org/spain/la-liga/matches"
driver.get(url)
completed_matches = driver.find_elements_by_xpath("""//*[@id="matches-list"]/div[@class='full-matches-table mt2e ' or @class='full-matches-table mt1e ']/div/div[2]/table[@class='matches-table inactive-matches']/tbody/tr[*]/td[3]/a[1]/span""");
print(len(completed_matches))
for match in completed_matches:
        match.click()
        print("Current driver URL: " + driver.current_url)
159
Current driver URL: https://footystats.org/spain/fc-barcelona-vs-real-club-deportivo-mallorca-h2h-stats#632514
---------------------------------------------------------------------------
StaleElementReferenceException            Traceback (most recent call last)
<ipython-input-3-da5851d767a8> in <module>
      4 print(len(completed_matches))
      5 for match in completed_matches:
----> 6         match.click()
      7         print("Current driver URL: " + driver.current_url)

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py in click(self)
     78     def click(self):
     79         """Clicks the element."""
---> 80         self._execute(Command.CLICK_ELEMENT)
     81 
     82     def submit(self):

~\Anaconda3\lib\site-packages\selenium\webdriver\remote\webelement.py in _execute(self, command, params)
    631             params = {}
    632         params['id'] = self._id
--> 633         return self._parent.execute(command, params)
    634 
    635     def find_element(self, by=By.ID, value=None):

~\Anaconda3\lib\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))

~\Anaconda3\lib\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=79.0.3945.79)
  (Driver info: chromedriver=72.0.3626.7 (efcef9a3ecda02b2132af215116a03852d08b9cb),platform=Windows NT 10.0.18362 x86_64)
159
当前驱动程序URL:https://footystats.org/spain/fc-barcelona-vs-real-club-deportivo-mallorca-h2h-stats#632514
---------------------------------------------------------------------------
StaleElementReferenceException回溯(最后一次最近调用)
在里面
4份打印(len(已完成的匹配))
5对于已完成的_匹配中的匹配:
---->6.匹配。单击()
7打印(“当前驱动程序URL:+driver.Current_URL”)
单击中的~\Anaconda3\lib\site packages\selenium\webdriver\remote\webelement.py(self)
78 def单击(自身):
79“单击元素。”“”
--->80自执行(命令。单击元素)
81
82 def提交(自我):
~\Anaconda3\lib\site packages\selenium\webdriver\remote\webelement.py in\u execute(self、command、params)
631参数={}
632参数['id']=self.\u id
-->633返回self.\u parent.execute(命令,参数)
634
635 def find_元素(self,by=by.ID,value=None):
执行中的~\Anaconda3\lib\site packages\selenium\webdriver\remote\webdriver.py(self,driver\u命令,参数)
319 response=self.command\u executor.execute(driver\u command,params)
320如果响应:
-->321自我错误处理程序检查响应(响应)
322响应['value']=self.\u展开值(
323响应。获取('值',无))
检查响应中的~\Anaconda3\lib\site packages\selenium\webdriver\remote\errorhandler.py(self,response)
240警报文本=值['alert']。获取('text')
241引发异常类(消息、屏幕、堆栈跟踪、警报文本)
-->242引发异常类(消息、屏幕、堆栈跟踪)
243
244定义值或默认值(self、obj、key、default):
StaleElementReferenceException:消息:stale元素引用:元素未附加到页面文档
(会话信息:chrome=79.0.3945.79)
(驱动程序信息:chromedriver=72.0.3626.7(efcef9a3ecda02b2132af215116a03852d08b9cb),平台=Windows NT 10.0.18362 x86_64)
完整的_matches列表包含159个html元素,但是for循环只显示第一个单击的链接,然后抛出StaleElementReferenceException


有人知道如何解决这个问题吗

您要查找的url位于您正在单击的链接中。要单击的父元素。StaleElementReferenceException是因为在单击链接后,页面会更改,呈现第一次单击stale之后的所有元素

from selenium import webdriver
import selenium
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome(r"C:\Users\Mart\Downloads\chromedriver_win32_2\chromedriver.exe")
url = "https://footystats.org/spain/la-liga/matches"
driver.get(url)
completed_matches = driver.find_elements_by_xpath("""//*[@id="matches-list"]/div[@class='full-matches-table mt2e ' or @class='full-matches-table mt1e ']/div/div[2]/table[@class='matches-table inactive-matches']/tbody/tr[*]/td[3]/a[1]/span""");
print(len(completed_matches))
for match in completed_matches:
        #match.click()
        #print("Current driver URL: " + driver.current_url)
        match_parent = match.find_element_by_xpath("..")
        href = match_parent.get_attribute("href")
        print("href: ", href)

单击之后,DOM将被刷新,因此出现StaleElementReferenceException。因此,在for循环内部构建完成的元素再次匹配

completed_matches = driver.find_elements_by_xpath("""//*[@id="matches-list"]/div[@class='full-matches-table mt2e ' or @class='full-matches-table mt1e ']/div/div[2]/table[@class='matches-table inactive-matches']/tbody/tr[*]/td[3]/a[1]/span""");
print(len(completed_matches))
for match in completed_matches:
    completed_matches = driver.find_elements_by_xpath("""//*[@id="matches-list"]/div[@class='full-matches-table mt2e ' or @class='full-matches-table mt1e ']/div/div[2]/table[@class='matches-table inactive-matches']/tbody/tr[*]/td[3]/a[1]/span""");
    match.click()

陈腐的意思是旧的、腐烂的、不再新鲜的。陈旧元素表示旧元素或不再可用的元素。假设在WebDriver中引用为WebElement的网页上有一个元素。如果DOM发生变化,那么WebElement就会过时

这意味着您正在工作的页面在单击元素后正在更改,因此我建议您进行修复:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
while True:
     try:
         completed_match = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.XPATH, "//*[@id="matches-list"]/div[@class='full-matches-table mt2e ")))
     except TimeoutException:
           break
     completed_match.click()
     time.sleep(2)
所以只要迭代元素并每次更新它,在这种情况下它肯定会在页面的DOM中

您可以在此处查看带有完整详细信息代码的Trip advisor web scraper: