【问题标题】:Selenium & Chrome using too much memorySelenium 和 Chrome 使用太多内存
【发布时间】:2017-07-28 20:15:47
【问题描述】:

我正在使用 Selenium/C# 和 Chrome 来报废一个网站,我需要滚动浏览一个列表,并报废它的元素,现在当我继续滚动时,新元素会显示出来,因为有数千个元素一旦计数达到 50 个元素,我将删除旧的,我正在使用 Javascript(注入)来实现这一点。

while (elementsCount > 50)
{
    ReadOnlyCollection<IWebElement> first = driver.FindElements(By.XPath("//div[@role='dialog']//ul/li[position() <= 10]//div[@class='_gzjax']/a")); // select the first 10 elements

    foreach (var item in first)
        elements.Add(item.Text); // keep the elements before deleting them

    // delete the first 10 elements
    js.ExecuteScript("for(count = 0; count < 10; count++){ " +
        "var elem = document.getElementsByClassName('_cx1ua')[0]; " +                                                   
        "elem.parentNode.removeChild(elem); }"); 
}

这很好用!

所以大多数时候,同时显示的元素不超过 60 个,现在我运行程序一段时间,报废的元素超过 10'000,Chrome 的内存增加,有时超过 2gb。

我什至尝试安装这个extension 来阻止图片下载(因为每个元素都附有图片)但仍然是同样的问题。

Chrome 是否在我不知情的情况下保存了某些内容?有什么办法可以删除它并保持当前页面的“状态”?

【问题讨论】:

  • 您似乎一直在添加到 elements,然后再也没有从中删除。
  • @TitusLucretius 元素实际上只是一个本地列表,与 Chrome 无关
  • 您能否发布您正在抓取的网站的 URL,并提供有关您要捕获的内容的更多信息?使用 JS 删除元素似乎是一种低效的方法。您是否尝试过手动进行此测试?使用脚本和手动使用的内存使用情况是否不同?
  • 如果元素与 JavaScript 事件绑定,我认为删除元素将无济于事,因为它们将作为分离的 DOM 留在内存中。
  • @JeffC 感谢 cmets,我正在尝试捕获 Instagram 用户关注者的用户名!当你点击关注者的按钮时,会出现一个对话框,里面有一个用户列表,这就是我正在滚动的内容。

标签: c# google-chrome selenium selenium-chromedriver


【解决方案1】:

Selenium 会为您的网络抓取工具带来大量开销,因为无论您是否看到窗口,它都将依赖浏览器的内存开销来呈现内容并将其显示给您的 selenium 驱动程序。

您有几个选项可以解决这个问题。

选项 1

我建议在http://html-agility-pack.net/?z=codeplex 使用 HtmlAgiltyPack 使用这个敏捷包,您可以解析节点并获取更多数据并相应地存储/操作。

在下面我的网络蜘蛛的示例中,我使用 MongoDB C# 驱动程序来传递数据,但是您看到的 HtmlDocument 是 HtmlAgility Pack 的一部分

    BsonArray IPageCrawler.CrawlForTags(Uri url, HtmlDocument doc)
    {
        var bsonTagArray = new BsonArray();
        if (doc.DocumentNode.SelectNodes("//*[self::h1 or self::h2 or self::h3]") == null)
        {
            return null;
        }
        foreach (var tag in doc.DocumentNode.SelectNodes("//*[self::h1 or self::h2 or self::h3]"))
        {
            if (tag.InnerHtml.Contains("href"))
            {
                var innerText = _contentHandler.CleanupString(tag.InnerText);
                bsonTagArray.Add(new BsonDocument(new BsonElement(tag.Name, innerText)));
            }
            else
            {
                var tagAtt = _contentHandler.CleanupString(tag.WriteContentTo());
                bsonTagArray.Add(new BsonDocument(new BsonElement(tag.Name, tagAtt)));
            }
        }
        return bsonTagArray;
   }

上面的代码将抓取页面中的所有超链接。我还有其他方法可以从任何页面抓取所有内容,到目前为止,即使在 4Gb 页面上也没有崩溃(因为下载的 zip 文件等)

选项 2

您可以继续使用 selenium,并尝试利用 selenium 或其他 3rd 方工具提供的无头浏览器支持来执行您的代码。 http://toolsqa.com/selenium-webdriver/headless-browser-testing-selenium-webdriver/

我相信 PhantomJS 是一个非常好的利用无头浏览器的方法,它会减少内存消耗http://phantomjs.org/

【讨论】:

  • 感谢您的回答!我没有使用 HtmlAgiltyPack 的原因是元素在你不断滚动时加载了 AJAX,所以我需要一个真正的浏览器来完成这项工作!我以前用过 PhantomJS,没想到它会比 Chrome 更好,我试试看告诉你
  • Chrome 现在可以无头浏览了
  • @TitusLucretius Chrome headless 不会减少内存使用(2017 年 8 月)。所以没用。
猜你喜欢
  • 1970-01-01
  • 2015-06-18
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
相关资源
最近更新 更多