private void CollectLinksToObjects(Object o) { //const int dublicateCountObjsToRecheck = 20; //string[] dublicateLastAddedLinks = new string[dublicateCountObjsToRecheck]; //int dublicateLoopCounter = 0; //bool[] dublicateMatrix = new bool[dublicateCountObjsToRecheck]; Instruction instruction = null; NetFetcher net = new NetFetcher(); bool stopLoop = false; Template template = o as Template; if (template == null) return; HtmlParser parser = new HtmlParser(); int countLinksObtained = -1; int countInstructions = 0; SortedList<int, bool> existingKeys = new SortedList<int, bool>();//список добавленных ключей do { if (countLinksObtained == 0)//если не нашли ниодной ссылки- сбрасываем текущие инструкции instruction = null; //if (dublicateLoopCounter >= dublicateCountObjsToRecheck - 1) //{ // instruction = null; // dublicateLoopCounter = 0; //} if (instruction == null || string.IsNullOrEmpty(instruction.link.Trim())) { //instruction = null; lock (instructionLocker) { if (instructions.Count() == 0) { Console.WriteLine("All instructions were processed, CollectLinksToObjects thread going to terminate"); eventLog.AddEventToLog("CollectLinksToObjects Инструкции закончились, завершаем работу"); break; } else { instruction = instructions.Dequeue();//берем инструкцию с очереди countInstructions = instructions.Count(); countLinksObtained = -1; } } } eventLog.AddEventToLog("CollectLinksToObjects количество инструкций в очереди: " + countInstructions.ToString()); string content = string.Empty; if (!stopLoop && instruction != null) { content = net.DownloadWebPage(instruction.link, Encoding.UTF8);//скачиваем страницу по линку из инструкций countLinksObtained = 0;//сбрасываем счетчик полученных линков foreach (var item in parser.GetLinks(content, instruction.host, template.links[0]))//получаем линки на объявления { if (string.IsNullOrEmpty(item)) continue; bool canAddToQueue = true; int currentKey = SearchIdFromURL(item.ToLower(), "ad_id"); if (existingKeys.ContainsKey(currentKey)) { canAddToQueue = false; eventLog.AddEventToLog("Найден дубликат в ключах url для " + currentKey.ToString()); } else existingKeys.Add(currentKey, true); //if(existingKeys.ContainsKey( //for (int i = 0; i < dublicateCountObjsToRecheck; i++) // if (dublicateLastAddedLinks[i] == item) // { // dublicateMatrix[i] = true;//dublicate found // canAddToQueue = false;//can't add current link to global queue // dublicateLoopCounter++;//считаем количество дубликатов // break; // } if (canAddToQueue)//in case no dublication for last elements { //if (dublicateLoopCounter >= dublicateCountObjsToRecheck - 1) // dublicateLoopCounter = 0; //dublicateLastAddedLinks[dublicateLoopCounter++] = item; int countLinksToObject = -1; Instruction linkToObj = new Instruction() { city = instruction.city, district = instruction.district, host = instruction.host, link = item, propertyAction = instruction.propertyAction, propertyType = instruction.propertyType }; lock (linksToObjectLocker) { linksToObjects.Enqueue(linkToObj);//adding url to object in global queue countLinksToObject = linksToObjects.Count; } Console.WriteLine("item: " + item); countLinksObtained++; linkToObj = null; lock (collectEntityLock)//разлочиваем сборку объектов { Monitor.PulseAll(collectEntityLock); } if (countLinksToObject >= LimitList)//если превышен лимит ссылок на объеты -лочимся { //lock (collectEntityLock)//разлочиваем сборку объектов //{ // Monitor.PulseAll(collectEntityLock); //} lock (linksToObjectLimitLocker) { Monitor.Wait(linksToObjectLimitLocker); } } } } string currentLink = instruction.link; if (template.pages[0].Count() > 1) { string tmpData = string.Empty; for (int i = 0; i < template.pages.Count - 1; i++) { if (string.IsNullOrEmpty(tmpData)) tmpData = parser.GetSingleContent(content, template.pages[i]); else tmpData = parser.GetSingleContent(tmpData, template.pages[i]); } foreach (var item in parser.GetLinks(tmpData, instruction.host, template.pages[template.pages.Count() - 1])) { instruction.link = item; break; } } else { foreach (var item in parser.GetLinks(content, instruction.host, template.pages[0])) { instruction.link = item; break; } } if (currentLink == instruction.link && countInstructions == 0)//если предыдущая ссылка и новая совпадают- достигли конца stopLoop = true; if (countLinksObtained == 0 && countInstructions == 0)//если предыдущая ссылка и новая совпадают- достигли конца stopLoop = true; } //if (string.IsNullOrEmpty(instruction.link) || stopLoop) //{ // stopLoop = false; // lock (instructionLocker) // { // if (instructions.Count > 0) // instruction = instructions.Dequeue(); // else stopLoop = true; // } //} } while (!stopLoop); lock (collectEntityLock)//разлочиваем ожидающий поток на прощание { Monitor.PulseAll(collectEntityLock); } Console.WriteLine("CollectLinksToObjects terminated"); return; }
private void CollectEntities(Object o) { lock (collectEntityLock)//лочим текущий поток чтобы не обгонять поток получения ссылок на объекты { Monitor.Wait(collectEntityLock); } NetFetcher net = new NetFetcher(); bool stopLoop = false; Template template = o as Template; if (template == null) return; HtmlParser parser = new HtmlParser(); DataExtactor extractor = new DataExtactor(); Instruction currentUrl = null; var sha = new System.Security.Cryptography.SHA256Managed(); var uEncode = new UnicodeEncoding(); List<ulong> h1 = null; int countLinksToObject = 0; try { do { lock (linksToObjectLocker) { if (linksToObjects.Count > 0) currentUrl = linksToObjects.Dequeue();//пытаемся получить ссылку на объект countLinksToObject = linksToObjects.Count(); } if (countLinksToObject <= minLimitList) { lock (linksToObjectLimitLocker) { Monitor.PulseAll(linksToObjectLimitLocker); } } if (currentUrl == null)//если ссылку получить не удалось { if (!t2.IsAlive)//пришло время останавливаться { eventLog.AddEventToLog("CollectEntities- Нет больше ссылок на объекты, поток собиратель ссылок- завршился- завершаем работу и мы"); break;//останавливаем главный цикл } else//поток собирающий ссылки еще живой { lock (linksToObjectLimitLocker) { Monitor.PulseAll(linksToObjectLimitLocker); } //eventLog.AddEventToLog("CollectEntities- Нет ссылок на объекты, поток собиратель еще живой- зысыпаем"); lock (collectEntityLock)//останавливаемся и ждем когда нас опять позовут { Monitor.Wait(collectEntityLock); } continue;//начинаем с начала цикла } } else//если ссылку получили { if (string.IsNullOrEmpty(currentUrl.link))//если урл ссылка пустая { eventLog.AddEventToLog("CollectEntities- ОШИБКА - пришла пустая ссылка"); continue;// начинаем цикл по новой } //если добрались сюда- значит ссылку получили и можем с ней работать #region проверяем линк на дубликаты bool dublicateLink = false; currentUrl.link = currentUrl.link.ToLower(); lock (processedLinksLocker) { if (processedLinks.ContainsKey(currentUrl.link)) { dublicateLink = true; currentUrl = null;//обнуляем текущую ссылку т.к. найден дубликат Console.WriteLine("dublicat found"); } } if (dublicateLink)//если нашли дубликат- начнаем с начала цикла continue; else//если дубликата не найден- добавлеям ссылку в список обработанных { lock (processedLinksLocker) { processedLinks.Add(currentUrl.link, true); linkLogger.AddLinkToLog(currentUrl.link); } } #endregion string content = net.DownloadWebPage(currentUrl.link, Encoding.UTF8);//скачиваем страницу Template tmpTemplate = Template.DeepClone<Template>(template);//делаем дубликат шаблона Entity ent = extractor.Extract(content, template.HOST, tmpTemplate);//template);//извлекаем объект со страницы if (ent != null)//если объект найден { #region проверяем текст объявления на дубликаты string clearContent = parser.ClearContent(ent.description); if (string.IsNullOrEmpty(clearContent))//если текст объявления после очистки пустой- пропускаем такое объявление { eventLog.AddEventToLog("ВНИМАНИЕ!!!Пустое объявление по ссылке " + ent.linkToOriginalObject); continue; } h1 = hash.ComputeHash(clearContent);//считаем хеши if (h1 == null) { eventLog.AddEventToLog("ВНИМАНИЕ!!!Ошибка получения хеша для " + clearContent); continue; } float percentage = hash.IsExist(h1);//проверяем на наличие похожих хешей if (percentage < 90.0) { hash.AddNewHash(h1);//добавляем если предел не превышен } else// найден дублика объявления { Console.WriteLine("Text Dublicate found"); ent = null; tmpTemplate = null; content = null; currentUrl = null; continue; } #endregion ent.linkToOriginalObject = currentUrl.link;//сохраняем линк на оригинал объявления if (string.IsNullOrEmpty(ent.phone1))//если телефон1 не заполнен еще- пытаемся его получить { //пытаемся получить телефоны foreach (var item in parser.GetLinks(content, template.HOST, template.phone[0])) { content = net.DownloadWebPage(item, Encoding.UTF8);//скачиваем указанную страницу для получения телефона var newPhoneTemplate = new string[1]; newPhoneTemplate[0] = template.phone[1]; extractor.ExtractPhone(content, ent, newPhoneTemplate); break; } } #region получаем фотографии if (ent.LinkToPhotos != null) { ent.photos = new List<byte[]>(); for (int i = 0; i < ent.LinkToPhotos.Count; i++) { if (!string.IsNullOrEmpty(ent.LinkToPhotos[i])) ent.photos.Add( net.getDataAsByteArray(ent.LinkToPhotos[i]) ); } } #endregion //дописываем вспомогательную информацию ent.propertyType = currentUrl.propertyType; ent.propertyAction = currentUrl.propertyAction; ent.City = currentUrl.city; ent.District = currentUrl.district; int countEntities = 0; lock (entitiesLocker)//добавляем полученый объект в очередь на сохранение { entities.Enqueue(ent); countEntities = entities.Count(); } ent = null; lock (dbLoaderLock) { Monitor.PulseAll(dbLoaderLock); } if (countEntities > LimitList)//если превысили лимит объектов в списке лочим текущий поток { lock (collectEntityLock) { Monitor.Wait(collectEntityLock); } } } else { eventLog.AddEventToLog("ОШИБКА объект по сслыке не найден: " + currentUrl.link); } } if (!t1.IsAlive && countLinksToObject == 0) stopLoop = true; } while (!stopLoop);//пока все условия соблюдаются } catch (Exception ex) { eventLog.AddEventToLog("ИСКЛЮЧЕНИЕ!!! CollectEntities " + ex.Message); hash.StoreCache();//сохряняем хеши } finally { lock (dbLoaderLock)//разлочиваем поток загрузки объектов в БД на прощание { Monitor.PulseAll(dbLoaderLock); } Console.WriteLine("CollectEntities terminated"); } return; }