Помогите с парсингом текста

ivanwork1

Новичок
Регистрация
24.05.2016
Сообщения
9
Благодарностей
0
Баллы
1
Доброе утром всем! Нужна ваша небольшая помощь. Целую ночь пытался сделать проект который бы парсил выдачу Яндекса. Нужен вот такой результат к примеру.


Купить розы саженцы дешево, Киев, Украина
sadco.com.ua›Купить розы
Купить саженцы клубники в питомнике в Украине. Купить саженцы плодовых деревьев в питомниках. ... Купить саженцы розы дешево Вы можете в современных украинских питомниках, в том числе и в нашем садовом центре.
Саженцы роз. Купить саженцы роз - цены оптовые...
Florium.ua›Флориум›Саженцы РОЗ
Роза – душистая красавица сада. Купить саженцы роз в Украине. ... Где купить розы саженцы дешево почтой. Во всем великолепном многообразии представлены саженцы роз в интернет магазине «Флориум».
Саженцы роз, купить в Украине, Киеве оптом и в розницу...
yaskravaklumba.com.ua›Саженцы роз
Несмотря на нестабильное экономическое положение, у нас все еще можно дешево купить саженцы роз в Украине. Это обусловлено самостоятельным формированием цен на собственную выращенную продукцию.
Саженцы роз. Товары и услуги компании "Долина роз"
agronomia.prom.ua›Саженцы роз
Купить Саженцы роз в Черновицкой области - цены, товары и услуги компании "Долина роз": +380 (93) 288-17-60 Татьяна консультант. ... Принимаем заказы на оптовые поставки саженцев роз по Украине.
Купить Саженцы Роз | Книп
knip.kiev.ua›sajentsy/rozyi
Саженцы Роз. Розы Блю Мун. Возраст саженца: 2 года. 50 грн. Купить. Роза Комт Де Шамбор. Возраст саженца: 2 года. 0 грн. Купить. Юбилей принца Монако.
Купить саженцы роз. Недорого. Киев, Украина.
sad.vert.ua›rozy.html
Купить саженцы роз в Киеве. Розы для посадки недорого. ... Розы для посадки недорого. Доставка по Украине. Нет в наличии.
Саженцы Роз - Сад / огород - OLX.ua
olx.ua›Дом и сад›Огород›Саженцы роз
Самые дешевые. ... » Продажа семян и саженцев - саженцы роз. ... Купить семена, подобрать средства и удобрения для ухода за растениями, настроить правильный полив - лишь часть забот настоящего огородника.
купить Саженцы роз в Украине от 35 грн. Доставка...
mriy.com.ua›Товар›Саженцы роз
Саженцы роз купить в Украине. В интернет-магазине Мрия представлен широкий ассортимент комнатных цветов, семян цветов и овощей, предметов декора для дома и сада. ... Новогодняя коллекция. Вместе дешевле. Акции.
Купить саженцы роз в городе Киев и Украине, сравнить...
ecoveles.com.ua›Саженцы роз
Саженцы роз можно купить в Украине удобным и очень простым способом. Важно не только найти самые красивые и ароматные сорта роз, но и приобрести здоровые саженцы.
Купити саджанці троянд; Замовлення саджанців троянд...
troyandy.org.ua›catalog
Саджанці троянд - вибір, замовлення, купівля, доставка. Коллекція троянд Григорія Мостіпаки. Україна. Киев.
Так как и выглядит выдачу, с переносами строк, ссылками и всем мусором. Но у меня возникла проблема, я не знаю как ее спарсить в таком виде. Пробовал с регуляркой, получалась каша, пробовал еще и через intrertext. Тоже не получилось, весь текст получается в одну строку.

Кто может подсказать, как спарсить текст так, как я привел в пример выше. Буду очень благодарен!
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Задачка интересная поэтому поковырялся.:-)

Для начала посмотрим на страницу и решим какие элементы будут вытаскиваться.
Вытаскиваться будут эти узлы через xpath, в них находится вся небходимая инфа.


Есть блоки с рекламой, а есть без. С рекламой будем выкидывать.
Как понять какие блоки с рекламой, а какие нет.

С рекламой


Без рекламы


Т.к. это "типа парсер" то страницы с яндекса будут браться через GET запрос, для скорости.:-)
Для работы с html страницей будет использоваться либа HtmlAgilityPack.dll.

Взяли страницу
Код:
var url = "https://yandex.ru/search/?lr=197&msid=1465109974.29885.22890.18047&text=%D0%9A%D1%83%D0%BF%D0%B8%D1%82%D1%8C%20%D1%80%D0%BE%D0%B7%D1%8B%20%D1%81%D0%B0%D0%B6%D0%B5%D0%BD%D1%86%D1%8B%20%D0%B4%D0%B5%D1%88%D0%B5%D0%B2%D0%BE%2C%20%D0%9A%D0%B8%D0%B5%D0%B2%2C%20%D0%A3%D0%BA%D1%80%D0%B0%D0%B8%D0%BD%D0%B0";

var response = ZennoPoster.HttpGet(
    url,
    "",
    "utf-8",
    InterfacesLibrary.Enums.Http.ResponceType.BodyOnly,
    5000,
    "",
    "",
    true,
    5,
    new []
    {
        "Host: yandex.ru",
        "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Encoding: gzip, deflate, sdch",
        "Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4",
        "Connection: keep-alive",
        "Upgrade-Insecure-Requests: 1"
    }
);

if(response == "")
{
    project.SendErrorToLog("Пустой ответ", true);
    return null;
}

return response;

Вытащили нужную инфу
Код:
var html = project.Variables["responseResult"].Value; // html страница

var doc = new HtmlDocument();
doc.LoadHtml(html); // создали объект HtmlDocument и загрузили в него html страницу

var nodes = doc.DocumentNode
    .SelectNodes(".//div[@class='serp-item']") // взяли нужные узлы
    .Select(n => n.FirstChild)
    .Where(n => n.FirstChild.GetAttributeValue("class", "") == "serp-item__title") // взяли без рекламы
    .ToList();
         

var list = new List<string>();

foreach (var node in nodes) // в цикле добавляем в список элемент состоящий из двух строчек
{
    var title = node.FirstChild.FirstChild.InnerText; // текст первой строчки
    var desc = node.SelectSingleNode(".//div[@class='path organic__path']").InnerText; // текст второй строчки

    list.Add(title + "\r\n" + desc); // добавил в список "двойную строчку"
}

var res = string.Join("\r\n", list); // объединил двойный строчки

return res;

Результат


 

Вложения

ivanwork1

Новичок
Регистрация
24.05.2016
Сообщения
9
Благодарностей
0
Баллы
1
Спасибо Вам огромное! Очень сильно помогли!
 

ivanwork1

Новичок
Регистрация
24.05.2016
Сообщения
9
Благодарностей
0
Баллы
1

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 039
Баллы
113
Код:
var url = "https://yandex.ru/search/?lr=197&msid=1465109974.29885.22890.18047&text=" + project.Variables["твоя переменая"].Value
 

kagorec

Client
Регистрация
24.08.2013
Сообщения
923
Благодарностей
476
Баллы
63
Отличное решение, а подскажите как можно каждый снипет (каждую строку индивидуально) обработать например:
* заменить символы на чтото свое
* перед каждой строкой добавить случайное словосочетание
:bw:
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
* заменить символы на чтото свое
Слишком абстрактно. Если в общим чертах то
Код:
var str = "какая то строка";
str = str.Replace("строка", "фигня");
На выходе будет - какая то фигня.

* перед каждой строкой добавить случайное словосочетание
Создается список с случайными фразами. Потом рандомно берется из этого списка, и добавляется куда надо.
Код:
var list = new[] {"вася", "петя", "коля"}; // список рандомных фраз
var rnd = new Random();
var i = rnd.Next(0, list.Count()); // берем случайное число в пределах размера коллекции
var str = list[i]; // получаем фразу из списка по индексу

Для маньяков xpath.:D
Вот это
Код:
var nodes = doc.DocumentNode
    .SelectNodes(".//div[@class='serp-item']") // взяли нужные узлы
    .Select(n => n.FirstChild)
    .Where(n => n.FirstChild.GetAttributeValue("class", "") == "serp-item__title") // взяли без рекламы
    .ToList();
       
var list = new List<string>();
foreach (var node in nodes) // в цикле добавляем в список элемент состоящий из двух строчек
{
    var title = node.FirstChild.FirstChild.InnerText; // текст первой строчки
    var desc = node.SelectSingleNode(".//div[@class='path organic__path']").InnerText; // текст второй строчки
    list.Add(title + "\r\n" + desc); // добавил в список "двойную строчку"
}
Можно заменить этим
Код:
var list = doc.DocumentNode
    .SelectNodes(".//div[@class='serp-item']/div/h2[@class='serp-item__title']") // взяли все узлы без рекламы
    .Select(n => // берем каждый узел и делаем из него выходную строку
        n.InnerText + // взяли inner text
        "\r\n" + // добавили перенос строки
        n.SelectSingleNode("../div/div[@class='path organic__path']").InnerText) // поднялись до родительского узла, а затем спустились к нужному и взяли inner text
    .ToList();
 

rostonix

Известная личность
Регистрация
23.12.2011
Сообщения
29 067
Благодарностей
5 707
Баллы
113
@Moadip ты крутой
 

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 039
Баллы
113

Sobesednic

Client
Регистрация
24.12.2012
Сообщения
391
Благодарностей
77
Баллы
28
@Moadip
Подскажите пожалуйста если нужно спарсить только титлы или снипетты что нужно докрутить в этом коде?

Пробую подставлять

Код:
.//*[@class='text organic__text'] и .//*[@class='serp-item__title']
но не получается побороть.

Спасибо заранее.

Код:
var html = project.Variables["responseResult"].Value; // html страница
var doc = new HtmlDocument();
doc.LoadHtml(html); // создали объект HtmlDocument и загрузили в него html страницу
var list = doc.DocumentNode
    .SelectNodes(".//div[@class='serp-item']/div/h2[@class='serp-item__title']") // взяли все узлы без рекламы
    .Select(n => // берем каждый узел и делаем из него выходную строку
        n.InnerText + // взяли inner text
        "\r\n" + // добавили перенос строки
        n.SelectSingleNode("../div/div[@class='path organic__path']").InnerText) // поднялись до родительского узла, а затем спустились к нужному и взяли inner text
    .ToList();
var res = string.Join("\r\n", list); // объединил двойный строчки
return res;
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Подскажите пожалуйста если нужно спарсить только титлы или снипетты что нужно докрутить в этом коде?
Титлы и сниппеты это что?:-)
Если бы на скрине показали что конкретно надо, то тогда бы проще было составить xpath для выдергивания элементов.
 
  • Спасибо
Реакции: Sobesednic

Sobesednic

Client
Регистрация
24.12.2012
Сообщения
391
Благодарностей
77
Баллы
28
В большей степени стоит вопрос как взять только одну нужную часть (допустим все титлы на странице) и положить в переменную.

Спасибо.

Титл <title>


description (снипетты)


 
Последнее редактирование:

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Ну вот как то так.
http://prnt.sc/cg2h5y
http://prnt.sc/cg2hjx

http://prnt.sc/cg2l83
http://prnt.sc/cg2lcs

Код:
var html = project.Variables["responseResult"].Value;
var doc = new HtmlDocument();
doc.LoadHtml(html);

var nodes = doc.DocumentNode
    .SelectNodes(".//div[@class='organic']/*[contains(@class, 'serp-item__title')]/*[contains(@class, 'serp-item__title')]")
    .Select(n => n.InnerText);

foreach(var node in nodes)
{
    project.SendInfoToLog(node);
}

//---

nodes = doc.DocumentNode
    .SelectNodes(".//div[@class='organic']/div/div[@class='text organic__text']")
    .Select(n => n.InnerText);

   
foreach(var node in nodes)
{
    project.SendInfoToLog(node);
}
В общем основная фишка в чем, это составить xpath до ноды где есть нужный текст.
Тут тоже хитрость, напрямую указать путь к какой то ноде редко получается, приходится спускаться от одной ноды к другой.
От той ноды, которая точно иденифицируется.

Текст, он там тоже может быть не чистый, а скажем в тех же тегах <b>.

Но HtmlAgilityPack это норм воспринимает, просто у нужной ноды вызывается метод InnerText и все, он вытаскивает весь текст.

Еще одна фишка, к примеру вот так
*[contains(@class, 'serp-item__title')]
Любой тег в котором есть атрибут class и в значении которого содержится serp-item__title

Или вот так
*[@class='serp-item__title')]
Любой тег в котором есть атрибут class и значение которого точно равно serp-item__title

Вроде бы одно и тоже, но нет, разные вещи.
Бывает что значение атрибута содержит какую то основную постоянную и еще там какую то приписку, а бывает что всегда одно и тоже.
Поэтому тут по ситуации. C contains конечно более универсально, но зато больше писать.))
 
  • Спасибо
Реакции: Sobesednic

Sobesednic

Client
Регистрация
24.12.2012
Сообщения
391
Благодарностей
77
Баллы
28
Подскажите как результат положить в переменную, вот результат, просто пишет (ок), в логе действий есть спаршенный текст.

Спасибо=))

 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Вернуть что то в свою переменную.
Но nodes в переменную не получится вернуть напрямую например так:
return nodes;

Т.к. в переменную можно вернуть только string, а nodes это IEnumerаble<string>.

Два варианта, или пихать в список, в зенке(думаю так как бы удобнее потом юзать), или если все таки надо в переменную, то например так:
return Join("\r\n", nodes);

Все что есть в перечислении, все элементы, объединятся в одну строку, и каждый элемент будет с новой строки.
Т.е вот так:
текст1
текст2
и т.д.

Если надо чтобы просто в одну строку, то тогда разделитель не "\r\n", новая строка, а " " - будет просто пробел.
 
  • Спасибо
Реакции: Sobesednic

Sobesednic

Client
Регистрация
24.12.2012
Сообщения
391
Благодарностей
77
Баллы
28
не хочет так выводить (return Join("\r\n", nodes); ошибка
Код:
"Ошибка в действии "CS0103" "Имя "Join" отсутствует в текущем контексте". [Строка: 12; Cтолбец: 8]"
Все разобрался, правильно так:

return string.Join("\r\n", nodes);

Еще раз огромное спасибо
 

ssXXXss

Client
Регистрация
23.12.2014
Сообщения
7 379
Благодарностей
2 039
Баллы
113
return string.Join("\r\n", nodes);
так попробуй
 
  • Спасибо
Реакции: Sobesednic

Sobesednic

Client
Регистрация
24.12.2012
Сообщения
391
Благодарностей
77
Баллы
28
@Moadip подскажите пожалуйста как вытянуть фото с помощью xpath по запросу с яндекса или гугла, что то не получается

тот же запрос тыц, как получить такую ссылку
Код:
http://knip.kiev.ua/uploads/0_3ddbc_7dd3a850_-1-L.jpg
 
Последнее редактирование:

amyboose

Client
Регистрация
21.04.2016
Сообщения
2 312
Благодарностей
1 191
Баллы
113
Moadip просто отлично шарит в парсинге. Возьму этот пост как один из примеров для изучения XPath
 

silent

Client
Регистрация
05.04.2014
Сообщения
237
Благодарностей
84
Баллы
28

Sobesednic

Client
Регистрация
24.12.2012
Сообщения
391
Благодарностей
77
Баллы
28

silent

Client
Регистрация
05.04.2014
Сообщения
237
Благодарностей
84
Баллы
28
  • Спасибо
Реакции: Sobesednic

Sobesednic

Client
Регистрация
24.12.2012
Сообщения
391
Благодарностей
77
Баллы
28
двумя действиями и у меня получается :-), хотелось бы одним если это возможно из этого блока вытащить <div class="rg_meta">
 

silent

Client
Регистрация
05.04.2014
Сообщения
237
Благодарностей
84
Баллы
28
двумя действиями и у меня получается :-), хотелось бы одним если это возможно из этого блока вытащить <div class="rg_meta">
а какая разница сколько действий, можешь конечно с помощью //div[@class="rg_meta"] забирать json и с ним уже работать, по любому будет больше 1 действия :-)
 
  • Спасибо
Реакции: Sobesednic

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
@Moadip подскажите пожалуйста как вытянуть фото с помощью xpath по запросу с яндекса или гугла, что то не получается
а какая разница сколько действий, можешь конечно с помощью //div[@class="rg_meta"] забирать json и с ним уже работать, по любому будет больше 1 действия :-)
Согласен. Не надо изобретать и пытаться все впихнуть в одно действие или одно выражение в коде.
Пусть лучше это будет несколько строк кода, но зато понятные.))
А по вопросу @silent уже ответил.
 
  • Спасибо
Реакции: Sobesednic

Pico

Client
Регистрация
24.05.2012
Сообщения
34
Благодарностей
5
Баллы
8
Здраствуйте ребята! При попытке выполнения проекта yaandex.xmlz выскакивает следующая ошибка ""The type or namespace name 'HtmlDocument' could not be found (are you missing a using directive or an assembly reference?)". [Строка: 3; Cтолбец: 15]". Библиотеку htmlagilitypack.dll в ExternalAssemblies добавил. Буду рад если кто-то сможет помочь.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Два варианта, или dll не добавлена в сам проект, или не прописан using HtmlAgilityPack;
Собственно об этом в ошибке и написано.

Можно из без прописывания, тогда надо писать так HtmlAgilityPack.HtmlDocument
 
  • Спасибо
Реакции: Pico

Pico

Client
Регистрация
24.05.2012
Сообщения
34
Благодарностей
5
Баллы
8
Два варианта, или dll не добавлена в сам проект, или не прописан using HtmlAgilityPack;
Собственно об этом в ошибке и написано.

Можно из без прописывания, тогда надо писать так HtmlAgilityPack.HtmlDocument
заменил var doc = new HtmlDocument(); на var doc = new HtmlAgilityPack.HtmlDocument();
Теперь появилась другая ошибка
"The type 'System.Xml.XPath.IXPathNavigable' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.". [Строка: 3; Cтолбец: 1]"
При этом директива using System.Xml прописана. У меня такое ощущение что моя зенька вообще игнорирует директивы.
upload_2016-12-23_18-44-29.png
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Проверь чтобы были эти либы
 
  • Спасибо
Реакции: Pico

Pico

Client
Регистрация
24.05.2012
Сообщения
34
Благодарностей
5
Баллы
8

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)