【问题标题】:StaleElementException while writing a text file in python using selenium webdriver使用 selenium webdriver 在 python 中编写文本文件时出现 StaleElementException
【发布时间】:2017-04-23 07:16:44
【问题描述】:

我正在尝试从 TripAdvisor 抓取酒店的评论并将其写入文本文件。到目前为止,代码运行良好,只是它时不时地在我编写文本文件的行上抛出 StaleElementException。这是我的代码:

for num in range(page_count):
    try:
        if num != 0:
            try:
                nxt = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "a.nav.next.rndBtn.ui_button.primary.taLnk")))
                #nxt = driver.find_element_by_css_selector("a.nav.next.rndBtn.ui_button.primary.taLnk")
                nxt.click()
                driver.implicitly_wait(5)
            except NoSuchElementException:
                driver.refresh()
                #driver.implicitly_wait(5)
                nxt = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "a.nav.next.rndBtn.ui_button.primary.taLnk")))
                nxt.click()
                driver.implicitly_wait(5)
        try:
            more = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span.taLnk.ulBlueLinks")))
            #more = driver.find_element_by_css_selector("span.taLnk.ulBlueLinks")
            more.click()
            time.sleep(1)
        except TimeoutException:
            print("There is no 'more' button on page %d" % (num+1))
        except WebDriverException:
            nxt = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "span.taLnk.ulBlueLinks")))
            nxt.click()
            driver.implicitly_wait(5)

        review_result = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'entry')))

        with open('New_Review.txt', 'a') as fid:
            for review in review_result:
                    fid.write(unidecode(review.text))
                    fid.write(sep)
                    fid.write(line_break)
        print ("processing done till page number %d" % (num+1))
    except StaleElementReferenceException:
        driver.refresh()
        driver.implicitly_wait(5)

        try:
            more = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span.taLnk.ulBlueLinks")))
            #more = driver.find_element_by_css_selector("span.taLnk.ulBlueLinks")
            more.click()
        except TimeoutException:
            print("There is no 'more' button on page %d" % (num+1))
        except WebDriverException:
            nxt = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "span.taLnk.ulBlueLinks")))
            nxt.click()
            driver.implicitly_wait(5)

        review_result = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'entry')))

        #print (review_result[1].text)
        with open('New_Review.csv', 'a') as fid:
            writer = csv.writer(fid, delimiter = ',', line_break = '\n')
            for review in review_result:
                    fid.write(unidecode(review.text))
                    fid.write(sep)
                    fid.write(line_break)
        print ("processing done till page number %d" % (num+1))    

这是错误:

StaleElementReferenceException:过时的元素引用:元素是 未附加到页面文档

回溯给出了这一行:

fid.write(unidecode(review.text))

我已经尝试处理异常,但它对我不起作用,我很难弄清楚我到底哪里错了。任何帮助表示赞赏!

【问题讨论】:

  • 我使用漂亮的汤和 xpath。硒对于刮擦来说有点脆弱。我用它来测试,但只是因为它有一些方便的内置东西。
  • 我打算使用 BeautifulSoup,但这段代码让我很难过,因为我无法理解这里的错误。
  • 您好,使用 WATIR(Ruby selenium binding 的包装器),您将永远不会遇到过时的元素问题,因为如果元素过时,WATIR 会重建元素。
  • 感谢 Gopal,您能否指导我访问某个链接,我可以在其中获得一些详细信息 - 不了解 Ruby 框架。

标签: python selenium selenium-webdriver web-scraping webdriver


【解决方案1】:

尝试创建辅助方法,例如

def get_text(locator):
   staled = True
   while staled:
     try:
        return WebDriverWait(driver, 10).until(EC.presence_of_element(locator)).text
    except StaleElementReferenceException:
       `log something or limit retry to certain times`

然后更改获取文本的方式

review_result = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located())
num_of_review - review_result.length
        with open('New_Review.txt', 'a') as fid:
            for index in range(1, num_of_review):
                    review_text = get_text((By.XPATH, "//*[@class='entry'][index]"))
                    fid.write(unidecode(review_text))
                    fid.write(sep)
                    fid.write(line_break)

【讨论】:

  • 我在 get_text 方法中收到未定义名称错误。
  • 你能粘贴错误堆栈跟踪吗?我写的一些语法需要完成或修复,但想法是您需要直接获取元素并检索文本,因为我认为您的页面可能会在 ypu 检索导致过时异常的文本时发生更改
  • 我无法将堆栈跟踪粘贴为编译时错误 - 所以当我在 Spyder 中编写此函数时看到此消息。但我明白你的意思,我只是想找出 get_text 方法的语法。
  • hmm,错误的语法与预期条件有关,你有没有像这样改行? ... review_element = WebDriverWait(driver, 10).until(EC.presence_of_element_located(locator)) return review_element.text 和关于异常处理
  • 但是如果我写EC.presence_of_element_located(locator),它不会只选择一个评论条目而不是列表!
猜你喜欢
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 2014-01-26
相关资源
最近更新 更多