Jump to content

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
Link to post
Share on other sites
 

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

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

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

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;
        }

 

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);

 

Link to post
Share on other sites
 
  • 2 weeks later...

JavaScript

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

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

 

Link to post
Share on other sites
 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Powered by Invision Community
Поддержка Invision Community в России

×
  • Create New...