在 Python 中使用 Selenium WebDriver 时处理 Firefox 无响应?

Posted

技术标签:

【中文标题】在 Python 中使用 Selenium WebDriver 时处理 Firefox 无响应?【英文标题】:Handle Firefox Not Responding While Using Selenium WebDriver With Python? 【发布时间】:2014-04-15 23:53:01 【问题描述】:

我正在使用 Selenium 和 Python 来测试网络应用程序;但是,Firefox 会定期进入“无响应”状态。当 Firefox 处于这种状态时,脚本会挂起,直到我关闭它。

我试过了:

br = webdriver.Firefox()
br.set_page_load_timeout(10)

br = webdriver.Firefox()
br.implicitly_wait(10)

我担心我的问题无法通过waittimeout 方法解决,因为该页面是Ajax。 .click().submit() 方法发送 POST 来回答问题,响应是字典,它通过 javascript 用新问题更新页面。 (这是我在谷歌Chrome开发者工具Ctrl+Shift+I中使用Network选项卡的理解)

问题是:

如何在 Selenium 中捕获 Firefox 无响应的情况?

我希望捕捉到这种情况,这样我就可以关闭浏览器并启动一个新浏览器。


ExperimentsWithCode 的回答之后编辑: 这是我的代码的 sn-p 来说明我的问题。

def answer_questions(self):
    q = QuestionParser(self.br.page_source)
    q.add_to_db()
    qid = q.get_qid()
    # My answer
    my_answer_id = q.get_my_answer()
    self.br.find_element_by_id(my_answer_id).click()
    # Submit answer
    self.br.find_element_by_xpath('//*[contains(@id, "submit_btn_")]').click()
    try:
        find_id = "submit_btn_" + str(qid)
        element = WebDriverWait(self.br,10).until(EC.presence_of_element_located((By.ID, find_id)))
    except:
        print 'I caught you'
    self.rnd(mu=7, s=2) # a method to sleep for a random time

我在循环中调用answer_questions() 方法。这段代码运行良好,直到 Firefox 崩溃,然后它会挂起,直到我关闭它。我read the docs 并担心我已经用尽了一切。问题是没有加载页面或元素。 问题是我不知道如何检测 Firefox 何时崩溃。 WebDriverWait 看起来很有希望,但当 Firefox 崩溃时它没有抛出 TimeoutException

感谢您的宝贵时间。


我想出了一个补救办法来解决我的问题。这是我所做的一个 sn-p:

import os, socket
from threading import Timer
def force_timeout(self):
    os.system('taskkill /im firefox.exe /f /t')
    # for Windows
    # /im firefox.exe is to select firefox
    # /f is to forcefully kill
    # /t is to kill all child processes

for i in range(0, 1000):
    try:
        t = Timer(60, self.force_timeout)
        # run force_timeout from new thread after 60 seconds
        t.start() # start timer
        self.answer_questions()
        # if self.answer_questions() finishes before 60s, cancel timer
        t.cancel() # cancel timer
    except socket.error:
        self.new_browser() # create a new browser
        self.login()       # login
        self.go_to_questions() # Go to questions page so the loop can continue
        # Code to recover from crash here

如果answer_questions() 方法未在 60 秒内完成,force_timeout() 将从新线程运行并强制终止 firefox.exe。一旦 Firefox 终止,代码将抛出 socket.error 错误。抓住这个错误,然后做你需要做的事情来从浏览器崩溃中恢复。我发现代码有点脏,但它完全按照我的需要工作。 供将来参考:操作系统 - Win8,Selenium 版本 - 2.40.0,Firefox 版本 - 27.0.1

Windows Taskkill Python threading.Timer

【问题讨论】:

问题是当页面没有完全加载浏览器或者你的代码正在等待响应。 @Vkt0rS。这不是我的情况。我的字面意思是 Firefox 没有响应,即我必须进入任务管理器才能强行杀死 Firefox。我用我用来解决问题的补救措施更新了我的问题,因为我得出结论 Selenium 无法处理处于无响应状态的浏览器。 非常好的补救措施!谢谢。不过,您可以将其发布为答案。 您不需要在except socket.error 分支中说t.cancel() 吗?否则,即使您尝试重新启动它,您的计时器也可能会杀死 firefox。 @max t.cancel() 必须尝试。如果 Firefox 停止响应,计时器将达到 60 秒并杀死 FireFox。如果 FireFox 没有崩溃,我们必须取消计时器,即t.cancel()。如果计时器达到 60 秒,force_timeout 方法将执行并杀死 FireFox,并抛出 socket.error 错误。 【参考方案1】:

对于那些使用 *nix 的人,

os.system("pkill -P %d firefox" % os.getpid())

可以很好地杀死当前进程的 Firefox 子进程。

pkill man page

【讨论】:

【参考方案2】:

Webdriver 文档有一个关于 here 之类的部分。

从文档中,您可以尝试显式等待:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0

br = webdriver.Firefox()
br.get("http://somedomain/url_that_delays_loading")
try:
    element = WebDriverWait(br, 10).until(EC.presence_of_element_located((By.ID, "_element_You_Are_Need_To_Load")))
finally:
    br.quit()

如果在 10 秒内找不到元素,这将超时,或者返回该窗口内的元素。

【讨论】:

谢谢,我试过你的建议;但是,当 Firefox 崩溃时,它并没有抛出 TimeoutException。脚本只是闲置,直到我关闭它。我更新了我的问题以反映这一点。 有没有可能元素已经加载而页面的其余部分没有?您可以尝试让它搜索该页面上不存在的 ID 并查看它是否收到 TimeoutException? 是的,我尝试搜索不存在的 ID,例如在我的问题的代码中,我这样做了:find_id = "1submit_btn_" + str(qid) 提交前面的额外1 不存在。代码按预期抛出错误。我的意思是 Firefox 真的崩溃了。我必须进入任务管理器强制关闭它。我希望 Selenium 有办法捕捉到这一点并强制关闭无响应的浏览器。 嗯...我不相信 selenium 能够处理崩溃。这个问题涉及如何在 n 秒后杀死 firefox 进程,但它是在 Java 中。 ***.com/questions/19991019/… 我试图避免手动编写函数来强制关闭 Firefox。我设计了一个解决我的问题的方法。它工作得很好,但有点“脏”。我用我的补救措施更新了我的问题。

以上是关于在 Python 中使用 Selenium WebDriver 时处理 Firefox 无响应?的主要内容,如果未能解决你的问题,请参考以下文章

Web自动化测试框架Selenium在Python中的使用

快速掌握Python Selenium Web自动化:二)Selenium操纵浏览器的最基本用例(转载)

selenium +python web自动化测试环境搭建

爬虫及web自动化SoEasy -- 使用python selenium 与 seleniumIDE

如何使用 selenium Web 驱动程序 python 在 html 中的标签之间添加标签

如何使用 Selenium Python 保存 Whatsapp web 的会话?