【问题标题】:Python, Selenium and Chromedriver - endless loop using find_element_by_id causes CPU problemPython、Selenium 和 Chromedriver - 使用 find_element_by_id 的无限循环导致 CPU 问题
【发布时间】:2018-12-07 08:54:22
【问题描述】:

大家好!我已经遇到这个问题一周了,但我认为我无法解决它,而且我也没有看到任何基于在线文章的解决方案。希望有人可以在这里帮助我...

我的场景: 我需要监控一个页面中 6 个不同表格的价格,这些表格几乎每秒都在变化。一天结束时,我会关闭浏览器(通过按 X 按钮)并终止脚本(通过按 Control+C),然后在早上再次运行并让它运行一整天。该脚本是用 python 编写的,并使用 selenium 来读取价格。我使用的浏览器是 Chrome。我的操作系统是 Windows 2008 R2; Selenium 版本是 3.14.1

这里是部分代码。它只是在以 1 秒为间隔的无限循环中使用 find_elements_by_id 简单地读取表格中的价格。

While True:
    close1 = float(browser.find_element_by_id('bnaBox1').find_elements_by_id('lastprc1')[0].text.encode('ascii','ignore'))
    close2 = float(browser.find_element_by_id('bnaBox2').find_elements_by_id('lastprc2')[0].text.encode('ascii','ignore'))
    close3 = float(browser.find_element_by_id('bnaBox3').find_elements_by_id('lastprc3')[0].text.encode('ascii','ignore'))
    close4 = float(browser.find_element_by_id('bnaBox4').find_elements_by_id('lastprc4')[0].text.encode('ascii','ignore'))
    close5 = float(browser.find_element_by_id('bnaBox5').find_elements_by_id('lastprc5')[0].text.encode('ascii','ignore'))
    close6 = float(browser.find_element_by_id('bnaBox6').find_elements_by_id('lastprc6')[0].text.encode('ascii','ignore'))
    time.sleep(1)
...

在运行的最初几分钟内,脚本消耗的 CPU 最少(大约 20~30%),但再过几分钟,消耗会慢慢上升到 100%!机器中除了脚本没有运行其他进程。

到目前为止我已经解决了问题(他们都没有解决我的问题)

  • 已将我的 chrome 升级到最新版本 - v71 和 chromerdriver 2.44
  • 将 Chrome 回滚到以前的版本(v62、v68、v69、v70)
  • 将 Chromedriver 版本回滚到 2.42 和 2.43
  • 清除了我的 %TEMP% 文件 -
  • 重启机器(多次)

该程序仅获取表中的值,但我怀疑在后台某处,当脚本运行时,不必要的数据堆积,导致 CPU 达到上限。

希望有人能帮我找出导致 CPU 出现此问题的原因并解决此问题。

【问题讨论】:

  • 在任务管理器中哪个应用占用高CPU?
  • Chrome.exe 位于任务管理器的顶部,消耗了大部分 cpu。它们消耗大约 30% ~ 50%。

标签: python selenium google-chrome selenium-chromedriver cpu-usage


【解决方案1】:

如果您的代码块没有任何可见性,特别是 WebDriver 配置,很难猜测 100% CPU 使用率 的确切原因。所以答案将非常基于通用指南,如下所示:

  • 永远不要关闭浏览器(按 X 按钮)。始终在 tearDown(){} 方法中调用 driver.quit() 以优雅地关闭和销毁 WebDriverWeb Client 实例。
  • 永远不要终止脚本(按 Control+C)。如果存在 zombie WebDriverWeb Browser 实例,您可以通过编程方式删除它们。
  • 几个有用的ChromeOptions()及其用法如下:

    options.addArguments("start-maximized"); // open Browser in maximized mode
    options.addArguments("disable-infobars"); // disabling infobars
    options.addArguments("--disable-extensions"); // disabling extensions
    options.addArguments("--disable-gpu"); // applicable to windows os only
    options.addArguments("--disable-dev-shm-usage"); // overcome limited resource problems
    options.addArguments("--no-sandbox"); // Bypass OS security model
    
  • 使用time.sleep(1) 形式的硬编码睡眠是一个很大的

  • 如果您在 headless 模式下使用 Chrome,关于 Chrome Headless 会话的 CPU 和内存消耗不可预测。
  • 始终使用最新发布的二进制文件更新您的测试环境,如下所示:
    • ChromeDriver 升级到当前的ChromeDriver v2.44 级别。
    • Chrome 版本保持在 Chrome v69-71 级别之间。 (as per ChromeDriver v2.44 release notes)
    • 清理你的项目工作区通过你的IDE重建你的项目只需要依赖。
    • 如果您的基础 Web Client 版本太旧,请通过 Revo Uninstaller 卸载它并安装最新的 GA 和发布版本的 Web Client
    • 进行系统重启
    • 执行您的@Test
  • 空间和内存管理的角度来看:

【讨论】:

【解决方案2】:

您是否尝试过将内存释放到循环中? 也许通过提取值(列表外的循环?)然后将这些变量重置为None,您可以避免过多的内存消耗。

...
while True:

...
    close1 = close2 = close3 = close4 = close5 = close6 = None

...

你也可以尝试强制垃圾收集器:

import gc

while True: 
...
    gc.collect()

如果您认为原因可能是脚本,另一种检测问题的解决方案可能是让 Chrome 执行remote debug 并调试页面。

--remote-debugging-port=9222

希望对你有所帮助。

【讨论】:

  • 来自评论:这看起来更像是评论,你能把它移到那里吗?
  • 感谢您的建议。我尝试通过将变量重置为 None 来释放内存,但它没有解决问题。我将尝试强制垃圾收集器并在此处发布更新...
猜你喜欢
  • 2018-08-18
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 2011-11-16
  • 1970-01-01
  • 2018-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多