【问题标题】:Selenium + Geckodriver troubleshootingSelenium + Geckodriver 故障排除
【发布时间】:2017-11-29 07:05:31
【问题描述】:

我在 Python 中使用带有 selenium 的 Firefox gecko 驱动程序来抓取论坛帖子标题,但遇到了一个我似乎无法弄清楚的问题。

~$ geckodriver --version
geckodriver 0.19.0

The source code of this program is available from
testing/geckodriver in https://hg.mozilla.org/mozilla-central.

This program is subject to the terms of the Mozilla Public License 2.0.
You can obtain a copy of the license at https://mozilla.org/MPL/2.0/.

我正在尝试从论坛上刮掉几年前的帖子标题,我的代码在一段时间内可以正常工作。我坐下来看着它运行了大约 20-30 分钟,它完全按照它应该做的事情做。然而,随后我启动​​脚本,然后上床睡觉,当我第二天早上醒来时,我发现它已经处理了大约 22,000 个帖子。我目前正在抓取的网站每页有 25 个帖子,因此它在崩溃之前通过了大约 880 个单独的 URL。

当它崩溃时会抛出以下错误:

WebDriverException: Message: Tried to run command without establishing a connection

最初我的代码如下所示:

FirefoxProfile = webdriver.FirefoxProfile('/home/me/jupyter-notebooks/FirefoxProfile/')
firefox_capabilities = DesiredCapabilities.FIREFOX
firefox_capabilities['marionette'] = True

driver = webdriver.Firefox(FirefoxProfile, capabilities=firefox_capabilities)
for url in urls:
    driver.get(url)
    ### code to process page here ###
driver.close()

我也试过了:

driver = webdriver.Firefox(FirefoxProfile, capabilities=firefox_capabilities)
for url in urls:
    driver.get(url)
    ### code to process page here ###
    driver.close()

for url in urls:
    driver = webdriver.Firefox(FirefoxProfile, capabilities=firefox_capabilities)
    driver.get(url)
    ### code to process page here ###
    driver.close()

我在所有 3 个场景中都遇到了同样的错误,但只是在它成功运行了一段时间之后,我不知道如何确定它失败的原因。

在成功处理数百个 url 后,如何确定为什么会出现此错误?还是有一些我没有遵循 Selenium/Firefox 处理这么多页面的最佳实践?

【问题讨论】:

    标签: python-2.7 selenium selenium-webdriver geckodriver firefox-marionette


    【解决方案1】:

    所有 3 个代码块都接近完美,但有如下小缺陷:

    您的第一个代码块是:

    driver = webdriver.Firefox(FirefoxProfile, capabilities=firefox_capabilities)
    for url in urls:
        driver.get(url)
        ### code to process page here ###
    driver.close()
    

    没有一个问题,代码块看起来很有希望。在根据 Best Practices 的最后一步中,我们必须调用 driver.quit() 而不是 driver.close(),这会阻止 webdriver 个实例位于 System Memory 中。你可以找到driver.close()driver.quit()here的区别。

    您的第二个代码块是:

    driver = webdriver.Firefox(FirefoxProfile, capabilities=firefox_capabilities)
    for url in urls:
        driver.get(url)
        ### code to process page here ###
        driver.close()
    

    这个块很容易出错。一旦执行进入for() 循环并在url 上运行,最后我们将关闭Browser Session/Instance。因此,当执行开始第二次迭代的循环时,driver.get(url) 上的脚本会出错,因为没有 Active Browser Session

    您的第三个代码块是:

    for url in urls:
        driver = webdriver.Firefox(FirefoxProfile, capabilities=firefox_capabilities)
        driver.get(url)
        ### code to process page here ###
        driver.close()
    

    代码块看起来非常组合,没有与第一个代码块相同的问题。在最后一步中,我们必须调用 driver.quit() 而不是 driver.close(),这将阻止 System Memory 中的悬空 webdriver 实例。由于悬空的 webdriver 实例会产生杂务并在某个时间点继续占用端口 WebDriver 无法找到空闲端口或无法打开新的Browser Session/Connection。因此,您会看到错误为 WebDriverException: Message: 尝试运行命令而不建立连接

    解决办法:

    根据Best Practices 尝试调用 driver.quit() 而不是 driver.close() 并打开一个新的 WebDriver 实例和一个新的 Web Browser Session

    【讨论】:

    • 感谢您的详细解释!这解决了这个问题,但现在我在运行一段时间后遇到了一个我无法弄清楚的 IO 错误。我会为此提出一个新问题。
    • IOError: [Errno 2] 没有这样的文件或目录:'/tmp/tmpYDZJ4E/webdriver-py-profilecopy/user.js'
    • 其实这个错误似乎和driver.quit()的改动有关。 Firefox 第一次打开时运行良好,但是在 .quit() 之后,它在尝试打开下一个窗口时会抛出此错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 2010-11-30
    • 2021-09-11
    • 2012-02-18
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多