---
title: "Функциональный граббинг сложных сайтов (yvision.kz)"
description: "На написание статьи меня натолкнула другая статья, пользователя @web - Простой граббинг, сложных сай..."
author: "Hes"
published: "2014-10-24T02:05:06+00:00"
modified: "2014-10-24T02:10:26+00:00"
locale: "ru"
canonical_url: "https://yvision.kz/post/funkcionalnyy-grabbing-slozhnyh-saytov-yvision-kz-435538"
markdown_url: "https://yvision.kz/post/funkcionalnyy-grabbing-slozhnyh-saytov-yvision-kz-435538/markdown"
site_name: "Yvision.kz"
---

# Функциональный граббинг сложных сайтов (yvision.kz)

> На написание статьи меня натолкнула другая статья, пользователя @web - Простой граббинг, сложных сай...

На написание статьи меня натолкнула другая статья, пользователя [@web](http://web.yvision.kz/) - [Простой граббинг, сложных сайтов. C# (на примере Yvision.kz)](http://yvision.kz/post/238540). В этой статье показано императивное решение задачи, я же задался вопросом - можно ли решить задачу, используя смешанные парадигмы, в частности функциональная (Linq) и императивная (ООП)?

Как оказалось - можно. Для этого я изначально поставил вопрос - что я хочу видеть в итоге? Есть сайт - Yvision, есть БД, куда надо будет сливать список статей, аналогично вышеуказанной статье, остается лишь мелочь - что же всё-таки мы будем сливать в БД?

Для этого был создан POCO-класс Yvision, который и будет характеризовать данные, которые мы хотим получить от сайта и которые мы будем записывать в БД.

- public class Yvision

- {

- ///

- /// Идентификатор статьи

- ///

- public string Id { get; set; }

- ///

- /// Наименование статьи

- ///

- public string Name { get; set; }

- ///

- /// Ссылка на статью

- ///

- public string [Link](http://www.php.net/link) { get; set; }

- ///

- /// Автор статьи

- ///

- public string Author { get; set; }

- ///

- /// Блог автора

- ///

- public string AuthorUrl { get; set; }

- ///

- /// Изображение статьи

- ///

- public string Image { get; set; }

- }

Дальше мне понадобился некий перечислитель, скрывающий методы работы с HtmlAgilityPack - так как программисту, пользующему библиотеку парсинга конкретно yvision.kz не всегда интересно знать как она устроена, главное, что она делает.

- public class YviEnumerable : IEnumerable

- {

- public YviEnumerable()

- {

- _yvisions = new HtmlWeb()

- .Load("http://www.yvision.kz")

- .DocumentNode

- //Выберем нужную нам ноду

- .SelectSingleNode("//div[@class=\"mainContent main_page\"]")

- //Выберем все дивы ноды

- .Descendants("div")

- //Где класс - статья

- .Where(d => d.Attributes.Contains("class") && d.Attributes["class"].Value.Contains("home_article1 big"))

- //Непосредственно трансформация данных

- .Select(node => new Yvision

- {

- //Id дива с которого берем данные

- Id = node.Id,

- //Url новости

- [Link](http://www.php.net/link) = _queryNodes(node, "hold").Element("a").Attributes["href"].Value,

- //Изображение

- Image = _queryNodes(node, "hold").ChildNodes.Elements("img").First().Attributes["src"].Value,

- //Наименование

- Name = _queryNodes(node, "text1").ChildNodes.Elements("a").First().InnerText,

- //Автор

- Author = _queryNodes(node, "author").Element("a").InnerText.[Trim](http://www.php.net/trim)(),

- //Блог автора

- AuthorUrl = _queryNodes(node, "author").Element("a").Attributes["href"].Value

- });

- }

- ///

- /// Коллекция новостей Yvision

- ///

- private readonly IEnumerable _yvisions;
- public IEnumerable Yvisions

- {

- get { return _yvisions; }

- }

- ///

- /// Функция выборки единичного элемента с заданным классом

- ///

- private readonly Func _queryNodes = (p, s) => p

- .Descendants("div")

- .First(d => d.Attributes.Contains("class") && d.Attributes["class"].Value.Contains(s));

- ///

- /// Возвращает перечислитель коллекции новостей

- ///

- ///

- public IEnumerator GetEnumerator()

- {

- return _yvisions.GetEnumerator();

- }

- IEnumerator IEnumerable.GetEnumerator()

- {

- return GetEnumerator();

- }

- }

Собственно на этом всё. Дальнейших танцев с бубнами особо не требуется - кое-где необходимо переписать стандартные функции на чистые (выбрасывать исключения нам не нужно) и даже местами можно улучшить код.

Использование перечислителя.

- private static void Main()

- {

- Console.ForegroundColor = ConsoleColor.White;
- foreach (var item in new YviEnumerable())

- {

- Console.WriteLine("postId: {0}, name: {1}, url: {2}, image: {3}, author: {4}, authorUrl: {5}", item.Id,

- item.Name, item.[Link](http://www.php.net/link),

- item.Image, item.Author, item.AuthorUrl);

- }

- Console.ReadLine();

- }

На этом всё, жду(или не жду:) без разницы) конструктивных комментариев.

Кстати результат исполнения программы:

![Функциональный граббинг сложных сайтов (yvision.kz)](http://storage.yvision.kz/images/user/hes/ajaTyFDgtvf7jx4ncT4641pNX4ZhsT.png)

---

Source: [https://yvision.kz/post/funkcionalnyy-grabbing-slozhnyh-saytov-yvision-kz-435538](https://yvision.kz/post/funkcionalnyy-grabbing-slozhnyh-saytov-yvision-kz-435538)