Я пишу программу для очистки множества веб-сайтов компаний (до 100 000) для получения актуальной контактной информации, а также некоторой информации об их сфере деятельности в C #. Поскольку большинство веб-сайтов не могут отображаться в обычном веб-браузере .NET, я использую geckofx для перехода на эти веб-сайты и для поиска релевантного мне контента, я выбираю узлы с помощью HtmlAgilityPack.
Процесс всегда один и тот же: если у меня есть URL-адрес для компании, я сразу захожу на веб-сайт, в противном случае я использую bing для поиска веб-адреса (Google, похоже, не нравится, когда он используется автоматически). На веб-сайте я ищу ссылку на выходные данные и ссылки на страницы, которые могут указывать на некоторую область деятельности, я перехожу к этим ссылкам и ищу ключевые фразы, которые я указал заранее. Все работает синхронно, я жду, пока браузер вызовет событие DocumentCompleted
каждый раз.
Пример:
//I navigate to bing looking for my company's name and postal code
Variables.browser.Navigate("https://www.bing.com/search?q=" + c.Name.Replace(" ", "+") + "+" + c.Zip.Replace(" ", "+"));
//I wait for the browser to finish loading. The Navigating event sets BrowserIsReady to false and the DocumentCompleted event sets it to true
do
{
f.Application.DoEvents();
} while (!Variables.BrowserIsReady);
HtmlDocument browserDoc = new HtmlDocument();
browserDoc.LoadHtml(Variables.browser.Document.Body.OuterHtml);
//I select the relevant node in the document
HtmlNode sidebarNode = browserDoc.DocumentNode.SelectSingleNode("//div[contains(concat(\" \", normalize-space(@class), \" \"), \" b_entityTP \")]");
if (sidebarNode != null)
{
Variables.logger.Log("Found readable sidebar. Loading data...");
string lookedUpName, lookedUpStreet, lookedUpCity, lookedUpZip, lookedUpPhone, lookedUpWebsite;
HtmlNode infoNode = sidebarNode.SelectSingleNode("//div[contains(concat(\" \", normalize-space(@class), \" \"), \" b_subModule \")]");
HtmlNode nameNode = infoNode.SelectSingleNode("//div[contains(concat(\" \", normalize-space(@class), \" \"), \" b_feedbackComponent \")]");
if (nameNode != null)
{
string[] dataFacts = nameNode.GetAttributeValue("data-facts", "").Replace("{\"", "").Replace("\"}", "").Split(new string[] { "\",\"" }, StringSplitOptions.None);
foreach (string dataFact in dataFacts)
{
//... abbreviated
}
}
//And at the end of every call to a node object I set it back to null
nameNode = null;
}
Мой geckofx не может записывать кеш в память или загружать изображения с веб-сайтов, которые я установил с помощью
GeckoPreferences.Default["browser.cache.memory.enabled"] = false;
GeckoPreferences.Default["permissions.default.image"] = 2;
перед созданием моего экземпляра GeckoWebBrowser.
После каждого очищенного сайта я звоню
//CookieMan is used as a global variable so I don't have to recreate it every time.
private static nsICookieManager CookieMan;
//...
CookieMan = Xpcom.GetService<nsICookieManager>("@mozilla.org/cookiemanager;1");
CookieMan = Xpcom.QueryInterface<nsICookieManager>(CookieMan);
CookieMan.RemoveAll();
Gecko.Cache.ImageCache.ClearCache(true);
Gecko.Cache.ImageCache.ClearCache(false);
Xpcom.GetService<nsIMemory>("@mozilla.org/xpcom/memory-service;1").HeapMinimize(true);
для удаления файлов cookie, кэша изображений (который, я не уверен, даже создан) и для минимизации использования памяти Xulrunners.
Тем не менее, после довольно приятного запуска с приблизительным временем выполнения 2-3 секунды на запись и комфортным использованием памяти в 200-300 МБ, оба быстро увеличивают расход до 16-17 секунд на запись и более 2 ГБ используемой памяти только для моего сканера после 1 час.
Я пытался форсировать сборку мусора с помощью GC.Collect();
(что, я знаю, вы не должны этого делать) и даже перерабатывать весь объект браузера, останавливая, удаляя и создавая его заново, чтобы попытаться избавиться от неиспользуемого мусора в памяти , но безрезультатно. Я также пытался выключить Xulrunner и запустить его снова, но Xpcom.Shutdown()
, кажется, останавливает все приложение, поэтому я не смог этого сделать.
На данный момент у меня почти нет идей, и я был бы очень признателен за новые советы по подходам, которые я еще не предпринял.