仅当我尝试两次收集(“抓取”)表的内容时,才会出现此问题。第一次读取表内容成功,但是第二次总是失败。
仅在Chrome浏览器(带有相应chromedriver的74版)上会发生这种情况。我用FireFox尝试了同样的方法,但从未发生过。我在Chrome中找到了一种解决方法,这没有任何意义,但确实可以解决问题。
当我“转到”除包含该表的屏幕以外的其他屏幕,然后返回时,表爬网成功。
以下是我用来收集表格的功能:
def Get_Faults_List(Port_Number=None, PSU=None, Retries=5):
for attempt in range(Retries):
try:
if Port_Number:
# Show the Faults view in the context of "Port_Number"
Device_Panel_Frame.Click_Port(self, Port_Number)
elif PSU:
if not Device_Panel_Frame.Click_PSU(self, PSU):
return None
Left_Panel_Frame.Click_Fault(self)
self.driver.switch_to_default_content()
Main_Body = self.driver.find_element_by_name('main_page')
self.driver.switch_to.frame(Main_Body)
alarms_tab = self.driver.find_element_by_id('tab_alarms')
alarms_tab.click()
Fault_Screen = self.driver.find_element_by_name('faults')
self.driver.switch_to.frame(Fault_Screen)
# the rows that the following variable collect are automatically
# the relevant fault lines. The XPATH that was used omits the two
# irrelevant lines
faultTable_rows = WebDriverWait(self.driver, timeout=3, poll_frequency=0.5).until(
EC.presence_of_all_elements_located((By.XPATH, "//table[@id='faultTab']//tr[not(@id or @style)]")))
current_faults = []
row_index = 0
for row in faultTable_rows: # Go through each of the rows
current_faults.append([])
# Collect all the column elements of a certain row into a list
faultTable_row_cols = row.find_elements_by_tag_name("td")
for col in faultTable_row_cols:
# Each row of the Faults table is separated into 5 columns each column holds a string
current_faults[row_index].append(col.text)
row_index += 1
break
except:
print(attempt + 1, 'attempt failed', Retries - (attempt + 1), 'to go')
self.Refresh_Screen()
sleep(5)
continue
如果我打开新的浏览器,我还将成功收集表格的内容。顺便说一句,故障总是发生在下表的第一行(标题之后)。该行是current_faults[row_index].append(col.text)
,我不明白为什么。例外没有任何意义。
还有另一种方法可以有效地爬网表的内容吗?
答案 0 :(得分:1)
有关获得Stale Element Reference Exception
的原因,请参见this answer。
当元素:{p>
- 已被删除
- 不再与DOM相连(如您的情况)
- 已更改
从文档中
您应该丢弃当前持有的引用并替换它,可能是通过将元素附加到DOM上再次找到它来实现。
即:再次“查找”该元素。
您可以依次使用driver.page_source
和Stale Element Reference Exception
html = driver.page_source
soup = BeautifulSoup(html, "lxml")
这应该在切换帧之后实现。
希望这对您有帮助!