Selenium爬虫调用函数后报StaleElementReferenceException错误如何解决
报错原因
StaleElementReferenceException 报错的核心是你先通过find_elements_by_xpath获取了所有<a>元素的引用存在elems列表中,后续遍历该列表时,原页面的DOM发生了变更(切换窗口回退、页面自动刷新、动态渲染更新都会导致原有DOM元素的引用失效),此时再对之前保存的元素对象调用get_attribute方法就会触发该异常。
解决方案
方案1:先提取所有链接存为字符串列表再遍历(最稳妥)
无需保留元素对象的引用,第一步先把所有符合规则的链接全部提取成纯字符串列表,后续直接遍历这个字符串列表处理即可,完全规避元素引用失效的问题。修改后的fetch_productlinks代码如下:
def fetch_productlinks(self, url): self.driver.get(url) # 先一次性提取所有符合条件的链接,存为普通字符串列表,不保留元素引用 elems = self.driver.find_elements_by_xpath("//a[@href]") valid_urls = [] for elem in elems: try: elem_url = elem.get_attribute("href") if re.match(".*/code/.*", elem_url): valid_urls.append(elem_url) except StaleElementReferenceException: # 提取链接阶段遇到失效的元素直接跳过即可 continue # 遍历纯字符串的链接列表,完全不会有元素引用问题 counter = 0 for elem_url in valid_urls: if counter <= 1: self.extract_imagesandmetadata(elem_url, self.driver) counter += 1
方案2:优化多窗口操作逻辑
你当前的extract_imagesandmetadata方法里新开标签页的逻辑也有优化空间,切换窗口后不需要操作原页面的元素,同时处理完后直接关闭新打开的标签页,减少不必要的窗口占用,也能降低原页面DOM变更的概率:
def extract_imagesandmetadata(self, url, driver): before_window = driver.current_window_handle # 用js新开标签页访问目标链接,避免触发原页面操作 driver.execute_script("window.open(arguments[0]);", url) # 切换到新标签页 new_window = [window for window in driver.window_handles if window != before_window][0] driver.switch_to.window(new_window) print("Crawling ..." + url) html = driver.page_source # 每次新建临时字典,避免全局变量覆盖之前的存储数据 tempdict = {} if html: self.soup = BeautifulSoup(html, 'html.parser') pimg = self.soup.find('img', {'class': 'img-responsive'}) if pimg: print(pimg["src"]) tempdict["pimg"] = self.img_base_path + pimg["src"] else: tempdict["pimg"] = "" ptitle = self.soup.find('h1', {'class': 'eprc-title'}) if ptitle: print(self.sanitize_text(ptitle.text)) tempdict["ptitle"] = self.sanitize_text(ptitle.text) else: tempdict["ptitle"] = "" tempdict["purl"] = url self.outdict.append(tempdict) # 处理完直接关闭当前新标签页,切回原窗口 driver.close() driver.switch_to.window(before_window)
额外注意
不要使用全局的self.tempdict存储单条产品数据,否则每次遍历都会覆盖之前的内容,最终所有存储的条目都会是最后一条产品的信息,每次处理新链接时新建临时字典即可。
内容的提问来源于stack exchange,提问作者Saurabh Saxena
相关产品推荐
相关产品推荐

