Jump to content
Sign in to follow this  
Константин Орлов

C# как сделать парсер в Visual Studio

Recommended Posts

Сделать парсер HTML-страниц на c# с хорошим функционалом не просто, надеюсь вам помогут статьи и прочие материалы, которые я нашел, пока разбирался в этой теме. Что нужно знать для начала?

 

  • AngleSharp - библиотека для парсинга (устанавливается в Visual Studio и подключается через using), собирает данные со страниц не открывая браузер.
  • Selenium WebDriver - штука для управления браузером через код  (устанавливается в Visual Studio и подключается через using), это не парсер в полном смысле слова, а лишь некий интерфейс, который может делать клики, искать элементы и т.п. При работе Селениум открывается браузер, которым управляет программа. И это не браузер в Visual Studio, а обычный Chrome. Может выполнять и JavaScripts код, и понимает XPath. Вообще это драйвер для браузера (т.е. штука, позволяющую им управлять), а не парсер, и не кликер.
  • XPath - язык запросов, чтобы найти конкретный элемент на странице (div, a, li, ul и т.п.), этим языком может пользоваться Selenium, чтобы обратиться к конкретному элементу.
  • LINQ C# - для прямо конкретной работы с информацией (сортировка, преобразование, выборка из массивов и списков) необходимо знать линк, можно и без него, просто кода будет больше и придется напрягаться.
  • JavaScript - код, который выполняется в браузере. Типо как C# только его выполнением и компиляцией занимается браузер.

 

XPath

  1. [C#] Введение в XPath на примере простого парсера - про то, как использовать выражения XPath, чтобы найти нужный элемент на странице.
  2. Примеры xpath-запросов к html - поможет немного въехать в синтаксис
  3. Введение в XPath (часть 1). Поддержка XPath в Selenium и инструментальные средства и Введение в XPath (часть 2). Основы построения запросов - похоже для JavaScript, но может пригодится (с C# синтаксис похожий)

 

AngleSharp

  1. Помогите написать самый простой парсер на AngleSharp [дубликат] - пример кода, как запустить парсер на AngleSharp (я не тестировал)
  2. Спарсить нужные теги C# AngleSharp? - "Но как мне спарсить все<img> теги, в которых атрибут src заканчивается на _200x300.jpg"
  3. Парсинг с C# AngleSharp - как получить URL из ссылки
  4. Как парсить страницу на AngleSharp? - чей-то консольный проект с рабочим парсером
  5. Как правильно парсить с помощью AngleSharp?

 

Selenium WebDriver

  1. Selenium WebDriver: поиск элементов на странице - похоже для JavaScript, но пригодиться может.
  2. Выберите родительский элемент известного элемента в Selenium - вопрос с ответом на каком-то из форумов
  3. WebDriver: характеристика основных команд 
  4. Selenium 2.0 — WebDriver. Впечатления, проблемы и советы по использованию - для тех, кто использует Селениум для тестирования интерфейсов сайтов.
  5. Автоматизированное тестирование веб-приложения (MS Unit Testing Framework + Selenium WebDriver C#). Часть 2.2: Selenium API wrapper — WebElement 
  6. Selenium 2.0 и WebDriver
  7. Про Selenium и один «велосипед» - опять для тестировщиков
  8. Парсинг сайтов на C# - Selenium  и HtmlAgilityPack 
  9. Top 100+ вопросов по Selenium, которые чаще всего задают на собеседованиях, с ответами

 

JavaScript

 

  1. [Урок 3] . Получение любой информации со страницы при помощи Javascript
  2. Как скрыть элемент?

 

LINQ C#

  1. LINQ C# - в работе навороченного парсера не обойтись без знания ЛИНК.
  2. Линк на professorweb.ru - неплохой сайт.
  3. Уроки C# – LINQ – Where, Select, GroupBy, AsParallel, x.Key – C# - отличный видеоурок по линк

 

Массивы и списки

  1. Убрать дубликаты из List - как при помощи linq удалить дубликаты из списка, в котором каждый элемент имеет свои поля, и необходимо сравнивать не сами объекты, а одно из их полей

 

С# всякое полезное

  1. Как удалить часть строки до определенного слова
  2. C# WebBrowser - браузер встроенный в C# Visual Studio, позволяет прямо в формах открывать браузер
  3. Парсинг сайтов на c#. Часть 1. Использование WebBrowser 
  4. C#, способы хранения настроек программы - сериализация или сохранение данных на HDD

 

Разное

  1. C# htmlagilitypack пример простого проекта - еще один парсер на си-шарп
  2. C# Agility pack HTML Парсер
  3. Разработка веб-скрапера для извлечения данных с портала открытых данных России data.gov.ru

Share this post


Link to post
Share on other sites

В данный момент я пишу парсер C# на Selenium, довольно тормозная штука, если необходимо спарсить со страницы несколько тысяч элементов. У меня страница на 3800 ссылок. Уже минут 20 Селением занимается следующей штукой - находит по заголовкам ссылку, переходит на 2 родительских элемента вверх, и добавляет этот элемент в список List<IWebElement>. Это прямо капец как медленно, но причина в том, что элементов много и делается это как бы не напрямую через код, а как бы через драйвер. По крайней мере мне кажется, что в этом причина. Ну и еще в том, что каждый раз, чтобы найти нужную ссылку ему приходится брать заголовок (их 2200 уникальных) и сравнивать со всеми 3800 ссылкам на странице, и так 2200 раз.

А еще Selenium WebDriver мне не нравится тем, что он, сцука, найдя элемент (например, блок div или ссылку) не может просто ее сохранить в виде кода, то есть как бы кешировать для своей дальнейшей работы (сам код он может предоставить). И если я обращаюсь к элементу, то он заново опрашивает браузер, то есть он хранит лишь ссылку на элементы (IWebElement), но не сами элементы.

И еще - основные посты про Selenium в интернете за 2012-14 годы...

Share this post


Link to post
Share on other sites

AngleSharp - операторы

Что и как можно изъять из ссылки?

 

У вас есть некий тип IElement, который получается, если спарсить IHtmlDocument iHtmlDocument (первое тип, второе имя переменной). В foreach вы можете обратиться так:

 

            foreach (IElement element in iHtmlDocument.QuerySelectorAll("a"))
            {
                ShowContent(element.Text());
                ShowContent(element.GetAttribute("href"));
                ShowContent(element.TextContent);
                ShowContent(element.InnerHtml);
                break;
            }

ShowContent моя функция, аналог вывода на консоль. В данном примере я спарсил html-документ, и через цикл обращаюсь к каждому тегу "a" этого документа. Вот что возвращает каждый из них:

 

//Заголовок ссылки
element.Text(); //Власти Петербурга объявили конкурс на реконструкцию СКК

//URL ссылки
element.GetAttribute("href"); //https://www.google.com/url?rct=j&sa=t&url=https://tass.ru/ekonomika/6962147&ct=ga&cd=CAAYADIZYjJmNjRkMWRiZjlhZjBmOTpydTpydTpSVQ&usg=AFQjCNFv6VH4P64l-HFUtm-BENZDLMkBTg

//весь текс (в данном случае это тоже заголовок)
element.TextContent; //Власти Петербурга объявили конкурс на реконструкцию СКК

//HTML который находится внутри элемента 
element.InnerHtml; //Власти Петербурга объявили конкурс на <b>реконструкцию</b> СКК

//HTML который находится вокргу элемента
element.OuterHtml; // <a class="result_title_link" href="https://www.google.com/url?rct=j&amp;sa=t&amp;url=https://tass.ru/ekonomika/6962147&amp;ct=ga&amp;cd=CAAYADIZYjJmNjRkMWRiZjlhZjBmOTpydTpydTpSVQ&amp;usg=AFQjCNFv6VH4P64l-HFUtm-BENZDLMkBTg" tabindex="0" target="_blank">Власти Петербурга объявили конкурс на <b>реконструкцию</b> СКК</a>

Сложные запросы LINQ C# AngleSharp

 

 

Пример: 

var resultParsing = document.QuerySelectorAll("a").Where(item => item.ClassName != null && item.ClassName.Contains("result_title_link"));

 

        //получаем из HTML-документа все теги нужного типа
        private IEnumerable<AngleSharp.Dom.IElement> ParseAllHeaders(IHtmlDocument document)
        {
            //ищем все теги "a" (ссылки)
            var resultParsing = document.QuerySelectorAll("a")
                //проверка на Null, что у ссылки есть поле "class"
                .Where(item => item.ClassName != null
                //выбираем только ссылки с классом из такого названия
                && item.ClassName.Contains("result_title_link"));

            //возвращаем результат
            return resultParsing;
        }

 

Share this post


Link to post
Share on other sites

Selenium WebDriver

Операторы, полезные для работы с управлением браузером через Селениум

 

Узнать если нужный текст на странице:

//собщит, есть ли нужный текст на странице (но не более, этот оператор не умеет находить по тексту нужный элемент)
//browser - переменная IWebDriver
bool info = browser.PageSource.Contains("текст для поиска");

Найти нужный элемент по тексту внутри него:

//создать переменную типа IWebElement, в которую будет помещен span, содержащий текст - нужный текст
IWebElement myElement = browser.FindElement(By.XPath("//span[contains(text(), 'нужный текст')]"));

Если тип HTML-тега контейнера не известен (div, span, li, ul и т.п.), то вместо него в Xpath ставьте звездочку *. Тогда найдется любой тег, содержащий данный текст.

 

Получить HTML-код элемента

 

Если вы нашли нужный элемент (IWebElement) через Selenium, то можете получить, как весь его код (включая сам элемент), так и только тот код, что он содержит внутри себя. Делается это через обращение к элементу, истребование его атрибута и нужно передать ему outerHTML либо innerHTML:

//вернет код в виде string всего элемента, включая его самого
textBox1.Text = tag1.GetAttribute("outerHTML");
//вернет только тот код, что находится внутри tag1 (не включая его самого)
textBox1.Text = tag1.GetAttribute("innerHTML");

Как в URL Selenium передать ссылку на файл на жестком диске?

 

Синтаксис такой:

browser.Navigate().GoToUrl("file:///D:/testparser/Эта_неделя_без_повторов.html");

Закрыть браузер

browser.Quit();

 

Выбор директории, откуда грузить пользователя

 

Зачем нужно не очень понятно, так как Selenium грузит какую-то особую копию браузера, но вдруг пригодится (и еще это может вызывать исключения, уже не помню почему). Способ запуска хрома под конкретным пользователем ниже.

//какого пользователя загружать (из C:\Users\Winda\AppData\Local\Google\Chrome\User Data)
chromeOptions.AddArgument("profile-directory=Profile 9");

 

Запуск браузера Chrome под конкретным пользователем

 

Если нужно, чтобы selenium запускал Хром с настройками конкретного профиля (а не каждый раз чистый), то можно попробовать следующее:

//создаем настройки для пользователя
ChromeOptions chromeOptions = new ChromeOptions();

//папка, которую создаст Selenium с сохраненными настройками пользователя
//теперь куки будут сохраняться в эту папку и грузиться оттуда
chromeOptions.AddArgument(@"user-data-dir=C:\profileChrome");

//открыть браузер и передать ему настройки
browser = new ChromeDriver(chromeOptions);

 

Share this post


Link to post
Share on other sites

JavaScript

Найти по ID элемент на странице и пометить его атрибутом с определенным значением

document.getElementById('айдишник_элемента').setAttribute('имя_атрибута', 'значение');

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×