место в рейтинге
  • 6050
  • 21
  • 11
Нравится блог?
Подписывайтесь!

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

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

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

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

   
  1. public class Yvision
  2. {
  3. /// <summary>
  4. /// Идентификатор статьи
  5. /// </summary>
  6. public string Id { get; set; }
  7. /// <summary>
  8. /// Наименование статьи
  9. /// </summary>
  10. public string Name { get; set; }
  11. /// <summary>
  12. /// Ссылка на статью
  13. /// </summary>
  14. public string Link { get; set; }
  15. /// <summary>
  16. /// Автор статьи
  17. /// </summary>
  18. public string Author { get; set; }
  19. /// <summary>
  20. /// Блог автора
  21. /// </summary>
  22. public string AuthorUrl { get; set; }
  23. /// <summary>
  24. /// Изображение статьи
  25. /// </summary>
  26. public string Image { get; set; }
  27. }

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

   
  1. public class YviEnumerable : IEnumerable<Yvision>
  2. {
  3. public YviEnumerable()
  4. {
  5. _yvisions = new HtmlWeb()
  6. .Load("http://www.yvision.kz")
  7. .DocumentNode
  8. //Выберем нужную нам ноду
  9. .SelectSingleNode("//div[@class=\"mainContent main_page\"]")
  10. //Выберем все дивы ноды
  11. .Descendants("div")
  12. //Где класс - статья
  13. .Where(d => d.Attributes.Contains("class") && d.Attributes["class"].Value.Contains("home_article1 big"))
  14. //Непосредственно трансформация данных
  15. .Select(node => new Yvision
  16. {
  17. //Id дива с которого берем данные
  18. Id = node.Id,
  19. //Url новости
  20. Link = _queryNodes(node, "hold").Element("a").Attributes["href"].Value,
  21. //Изображение
  22. Image = _queryNodes(node, "hold").ChildNodes.Elements("img").First().Attributes["src"].Value,
  23. //Наименование
  24. Name = _queryNodes(node, "text1").ChildNodes.Elements("a").First().InnerText,
  25. //Автор
  26. Author = _queryNodes(node, "author").Element("a").InnerText.Trim(),
  27. //Блог автора
  28. AuthorUrl = _queryNodes(node, "author").Element("a").Attributes["href"].Value
  29. });
  30. }
  31. /// <summary>
  32. /// Коллекция новостей Yvision
  33. /// </summary>
  34. private readonly IEnumerable<Yvision> _yvisions;
  35. public IEnumerable<Yvision> Yvisions
  36. {
  37. get { return _yvisions; }
  38. }
  39. /// <summary>
  40. /// Функция выборки единичного элемента с заданным классом
  41. /// </summary>
  42. private readonly Func<HtmlNode, string, HtmlNode> _queryNodes = (p, s) => p
  43. .Descendants("div")
  44. .First(d => d.Attributes.Contains("class") && d.Attributes["class"].Value.Contains(s));
  45. /// <summary>
  46. /// Возвращает перечислитель коллекции новостей
  47. /// </summary>
  48. /// <returns></returns>
  49. public IEnumerator<Yvision> GetEnumerator()
  50. {
  51. return _yvisions.GetEnumerator();
  52. }
  53. IEnumerator IEnumerable.GetEnumerator()
  54. {
  55. return GetEnumerator();
  56. }
  57. }

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

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

   
  1. private static void Main()
  2. {
  3. Console.ForegroundColor = ConsoleColor.White;
  4. foreach (var item in new YviEnumerable())
  5. {
  6. Console.WriteLine("postId: {0}, name: {1}, url: {2}, image: {3}, author: {4}, authorUrl: {5}", item.Id,
  7. item.Name, item.Link,
  8. item.Image, item.Author, item.AuthorUrl);
  9. }
  10. Console.ReadLine();
  11. }

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

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

Hes
24 октября 2014, 14:05
1033

Загрузка...
Loading...

Комментарии

Hes
0
8
Пока нет комментов, небольшая подсказка. Побочный эффект может возникать в этом месте:
.Select(node => new Yvision
{
............
}
Спасибо, за статью.
Я новичок в мире ООП, а основной заработок на начальных порах, в мире фриланс для C#, похоже строится на парсинге.
ХАП, XML, XPath в нагрузку к C#, для самообучения - это полный алес. Без подобных статей, c использованием особенностей именно C# разобраться в теме довольно сложно. Благодарю.
Hes
0
11
Ну здесь немного не об ООП. Тут больше о Linq - msdn.microsoft.com Чтобы лучше понять ООП, лучше всего посмотреть на готовые проекты (например на гитхабе), на паттерны проектирования. Паттерны в дотнете - habrahabr.ru шпаргалка по паттернам - habrahabr.ru

Оставьте свой комментарий

Спасибо за открытие блога в Yvision.kz! Чтобы убедиться в отсутствии спама, все комментарии новых пользователей проходят премодерацию. Соблюдение правил нашей блог-платформы ускорит ваш переход в категорию надежных пользователей, не нуждающихся в премодерации. Обязательно прочтите наши правила по указанной ссылке: Правила

Также можно нажать Ctrl+Enter

Популярные посты

Мой дом – не гостиница. Я не останавливаюсь у своей родни, потому что знаю, что это такое

Мой дом – не гостиница. Я не останавливаюсь у своей родни, потому что знаю, что это такое

Наступил долгожданный момент и мы смогли заселиться в собственную квартиру. А потом началось... Все знакомые, родственники, даже коллеги и соседи родителей вспомнили о нашем существовании.
Idealovnet
14 окт. 2017 / 20:38
  • 8830
  • 82
Работа на EXPO. «Улыбайтесь, вы – лица Казахстана»

Работа на EXPO. «Улыбайтесь, вы – лица Казахстана»

Продление перерывов, втыки от менеджеров, борьба за стенды, кучкования, как мы друг-друга прикрывали, защищали от гостей. Все эти события доставляли радость, и каждый день на работу я приходила...
madiNAtty
14 окт. 2017 / 22:34
  • 6096
  • 23
О проститутках, ЗППП и других сексуальных страстях

О проститутках, ЗППП и других сексуальных страстях

У меня обширный сексуальный опыт, и я этим не хвастаюсь. Будь у меня возможность, променял бы это всё на одного партнёра. Но так как с личной жизнью не заладилось, а секс я очень люблю, то приходилось изворачиваться.
bez_prav
18 окт. 2017 / 18:01
Я четко помню тот день, когда мне позвонили друзья и сообщили: «Она выходит замуж»

Я четко помню тот день, когда мне позвонили друзья и сообщили: «Она выходит замуж»

У нас была особенная атмосфера, мы постоянно были вместе, читали треки, летом часто поднимались в горы. Гуляли пешком по ночному городу, иногда до утра. Снимали хату и представляли совместную жизнь...
Dominator-kz
14 окт. 2017 / 22:29
Отчего в Казахстане предвзятое отношение к отечественному продукту?

Отчего в Казахстане предвзятое отношение к отечественному продукту?

Вы когда-нибудь пользовались казахстанской косметикой? Я тоже нет, поэтому сразу же откликнулась на приглашение своего фейсбук-френда протестировать отечественные крема… из Степногорска.
Shimanskaya
16 окт. 2017 / 11:32
  • 2750
  • 30
Я помню тот день, когда мне позвонили друзья и сообщили: «Она выходит замуж». Часть 2

Я помню тот день, когда мне позвонили друзья и сообщили: «Она выходит замуж». Часть 2

Я знал дату свадьбы. За неделю до свадьбы в соцсети "Вконтакте" на все мои последние фото, был проставлен лайк с её профиля. Сердце забилось сильнее. В душе загорелась наивная, крошечная надежда.
Dominator-kz
17 окт. 2017 / 15:41
Мой парень – «тиран». Почему я вступила в такие отношения?

Мой парень – «тиран». Почему я вступила в такие отношения?

История из моей жизни. Я вспоминаю эти отношения и сама не могу понять - как так произошло? А дело в том, что вы и сами не заметите. Это наступает плавно и динамично.
Altynai_JA
18 окт. 2017 / 14:17
«Автобусная неделя». Выдержит ли аким Шымкента давку в общественном транспорте?

«Автобусная неделя». Выдержит ли аким Шымкента давку в общественном транспорте?

Аким Шымкента Габидулла Абдрахимов нашёл решение накопившихся проблем городского транспорта. Все ключевые работники акимата некоторое время будут сами ездить на автобусах.
openqazaqstan
18 окт. 2017 / 10:53
  • 1635
  • 30
Аркадий Волож привел в Казахстан «Яндекс.Лицей». Плакать или радоваться?

Аркадий Волож привел в Казахстан «Яндекс.Лицей». Плакать или радоваться?

"Яндекс.Лицей" зашел в казахстанские школы. План - учить бесплатно программированию, формировать себе кадры и выйти на мощность 10 тысяч школьников в год.
Zhumanova
18 окт. 2017 / 8:36
  • 1429
  • 10