使用Python迭代时发生StaleElementException

时间:2018-12-05 21:23:06

标签: python selenium xpath webdriverwait staleelementreferenceexception

我正在尝试为Amazon结果创建一个基本的Web抓取工具。在遍历结果时,有时会进入结果的第5页(有时只有第2页),然后抛出StaleElementException。在引发异常后查看浏览器时,我可以看到驱动程序/页面没有向下滚动到页码所在的位置(底部栏)。

我的代码:

driver.get('https://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&field-keywords=sonicare+toothbrush')

for page in range(1,last_page_number +1):

    driver.implicitly_wait(10)

    bottom_bar = driver.find_element_by_class_name('pagnCur')
    driver.execute_script("arguments[0].scrollIntoView(true);", bottom_bar)

    current_page_number = int(driver.find_element_by_class_name('pagnCur').text)

    if page == current_page_number:
        next_page = driver.find_element_by_xpath('//div[@id="pagn"]/span[@class="pagnLink"]/a[text()="{0}"]'.format(current_page_number+1))
        next_page.click()
        print('page #',page,': going to next page')
    else:
        print('page #: ', page,'error')

我已经看过这个question,并且我猜想可以应用类似的修复程序,但是我不确定如何在页面上找到消失的东西。另外,根据打印语句的执行速度,我可以看到implicitly_wait(10)实际上并没有等待整整10秒钟。

异常指向以“ driver.execute_script”开头的行。例外:

StaleElementReferenceException: Message: The element reference of <span class="pagnCur"> 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

有时我会遇到ValueError:

ValueError: invalid literal for int() with base 10: ''

因此,这些错误/异常使我相信等待页面完全刷新时会发生某些事情。

2 个答案:

答案 0 :(得分:3)

如果只希望脚本遍历所有结果页面,则不需要任何复杂的逻辑-只要有可能,只需单击“下一步”按钮即可:

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait as wait
from selenium.common.exceptions import TimeoutException

driver = webdriver.Chrome()

driver.get('https://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&field-keywords=sonicare+toothbrush')

while True:
    try:
        wait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a > span#pagnNextString'))).click()
    except TimeoutException:
        break

P.S。另请注意,implicitly_wait(10)不应等待整整10秒,而应等待最长等待10秒,以使元素出现在HTML DOM 中。因此,如果在1或2秒钟内找到了元素,则等待完成,而您不会等待8-9秒钟的休息...

答案 1 :(得分:2)

看来您快到了。

通过which() printing 几个有用的调试消息来保留 scrolling 的概念,我做了一些细微的调整,使 WebDriverWait ,您可以使用以下解决方案:

  • 代码块:

    $oldv = 0;
    while ($selt=mysql_fetch_array($sel)) {
     $oldv = ($oldv == 0) ? $value : $oldv;
     $value= $selt['value'];
     $ser=$selt['serial'];
     $dd=$selt['date'];
     echo $subtract = $value - $oldv;
     echo $oldv = $value;
    }
    
  • 控制台输出:

    scrollIntoView()