【问题标题】:Selenium not freeing up memory even after calling close/quit即使在调用关闭/退出后,Selenium 也不会释放内存
【发布时间】:2016-11-05 00:00:46
【问题描述】:

所以我一直在研究可以处理 10k+ 页并从中抓取数据的刮刀。

问题在于,随着时间的推移,内存消耗会急剧增加。所以为了克服这个问题 - 而不是只在抓取结束时关闭驱动程序实例 - 更新抓取器,以便在加载每个页面并提取数据后关闭实例。

但由于某种原因,ram 内存仍然会被填充。

我尝试使用 PhantomJS,但由于某种原因它无法正确加载数据。 我还尝试使用刮板的初始版本将 Firefox 中的缓存限制为 100mb,但这也不起作用。

注意:我使用 chromedriver 和 firefox 运行测试,不幸的是我不能使用 requests、mechanize 等库来代替 selenium。

感谢任何帮助,因为我已经尝试了一周的时间来解决这个问题。谢谢。

【问题讨论】:

    标签: python selenium firefox selenium-webdriver selenium-chromedriver


    【解决方案1】:

    The only way 强制 Python 解释器向操作系统释放内存就是终止进程。因此,使用multiprocessing 来生成 selenium Firefox 实例;当生成的进程终止时,内存将被释放:

    import multiprocessing as mp
    import selenium.webdriver as webdriver
    
    def worker()
        driver = webdriver.Firefox()
        # do memory-intensive work
        # closing and quitting is not what ultimately frees the memory, but it
        # is good to close the WebDriver session gracefully anyway.
        driver.close()
        driver.quit()
    
    if __name__ == '__main__':
        p = mp.Process(target=worker)
        # run `worker` in a subprocess
        p.start()
        # make the main process wait for `worker` to end
        p.join()
        # all memory used by the subprocess will be freed to the OS
    

    另见Why doesn't Python release the memory when I delete a large object?

    【讨论】:

    • 我认为这是解决这个问题的方法!
    【解决方案2】:

    您的意思是说您的驱动程序正在填满您的记忆吗?你是如何关闭它们的?如果您正在提取数据,您是否仍然引用一些将它们存储在内存中的集合?

    您提到,当您在抓取结束时关闭驱动程序实例时,您的内存已经用完了,这看起来像是您保留了额外的引用。

    【讨论】:

    • 是的,似乎驱动程序正在填满内存。我有 5 个使用 Selenium 的功能。我在 Scrapy 旁边使用硒。所以在这些函数中我只是实例化新的驱动程序实例,然后在函数的近端调用 driver.quit() 或 driver.close()。至于保留额外的参考资料,我不确定我是否这样做。我使用 selenium 加载页面,一旦加载,我将 page_source 放入 Scrapy 选择器。我在 Scrapy 中没有任何内存泄漏。
    • 您可以使用memory_profiler逐行检查内存使用情况(在您的程序而不是网站中)。这应该有助于更好地了解哪个部分正在消耗您的内存。如果您在那里找不到任何东西,在此处发布示例函数可能会有所帮助。
    • @ScrapyNoob 还检查顶部是否有您使用的任何浏览器的多个实例。
    【解决方案3】:

    在将 webdriver.get(url) 语句放入 try/except/finally 语句之前,我遇到了同样的问题,并确保 webdriver.quit() 在 finally 语句中,这样,它总是会执行。喜欢:

    webdriver = webdriver.Firefox()
    try:
            webdriver.get(url)
            source_body = webdriver.page_source
    except Exception as e:
            print(e)
    finally:
            webdriver.quit()
    

    来自docs

    此类语句的 finally 子句可用于指定清理 不处理异常的代码,但无论是否执行 上述代码中是否发生异常。

    【讨论】:

      【解决方案4】:

      我遇到过类似的问题,我自己销毁了那个驱动程序(即将驱动程序设置为无)可以防止我的内存泄漏

      【讨论】:

        猜你喜欢
        • 2011-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-07
        • 1970-01-01
        • 1970-01-01
        • 2011-02-25
        • 2012-10-19
        相关资源
        最近更新 更多