Учебное пособие по веб-парсингу с помощью C#

Лучшие библиотеки для веб-парсинга на C#

Веб-парсинг становится проще, если использовать правильные инструменты. Давайте рассмотрим лучшие библиотеки NuGet для парсинга на C#:  
  • HtmlAgilityPack: самая популярная библиотека парсеров на C#. HtmlAgilityPack предоставляет вам возможность загружать веб-страницы, анализировать их HTML-содержимое, выбирать HTML-элементы и извлекать из них нужные данные.  
  • HttpClient: самый популярный HTTP-клиент на языке C#. HttpClient особенно полезен, когда речь идет о веб-краулинге, поскольку позволяет выполнять HTTP-запросы легко и асинхронно.  
  • Selenium WebDriver — библиотека, которая поддерживает несколько языков программирования и позволяет писать автоматизированные тесты для веб-приложений. Вы также можете использовать ее для веб-парсинга.  
  • Puppeteer Sharp — C#-порт Puppeteer. Puppeteer Sharp предоставляет возможности безголового браузера и позволяет использовать для веб-парсинга страницы с динамическим контентом.  
В этом руководстве будет показано, как выполнить веб-парсинг с использованием C#, а также HtmlAgilityPack и Selenium.  

Необходимые предварительные установки для веб-парсинга с помощью C#

Прежде чем написать первую строчку кода вашего веб-парсера на C#, вам необходимо выполнить некоторые предварительные условия:
  • Visual Studio: подойдет бесплатная Community-версия Visual Studio 2022.  
  • .NET 6+: подойдет любая версия LTS начиная с шестой.  
Теперь вы готовы к созданию проекта веб-парсинга на языке C# в Visual Studio.

Настройка проекта в Visual Studio

Откройте Visual Studio и нажмите на опцию «Create a new project».
В окне «Create a new project» выберите опцию «C#» из выпадающего списка. После указания языка программирования выберите шаблон «Console App» и нажмите кнопку «Next».
Затем назовите свой проект StaticWebScraping, нажмите «Select» и выберите версию .NET. Если вы установили .NET 6.0, Visual Studio уже должна выбрать ее за вас.  
Нажмите кнопку «Create», чтобы инициализировать ваш проект веб-парсинга на C#. Visual Studio инициализирует папку StaticWebScraping, содержащую файл App.cs. В этом файле будет храниться логика веб-парсингана C#:  
namespace WebScraping {
    public class Program {
            public static void Main() {
               // scraping logic...               
            }
    }
}
Пришло время понять, как создать веб-парсер на C#!

Веб-парсинг сайтов со статическим контентом с помощью C#

На статических сайтах контент веб-страниц хранится в возвращаемых сервером HTML-документах. Это означает, что веб-страница со статическим содержимым не выполняет XHR-запросы для получения данных и не требует выполнения JavaScript.  
Парсинг статических сайтов довольно прост. Все, что вам нужно сделать, это:
  • Установите библиотеку C# для веб-парсинга
  • Загрузите целевую веб-страницу и спарсите ее HTML-документ
  • Используйте библиотеку веб-парсинга для выбора интересующих вас элементов HTML
  • Извлеките из них данные
Давайте применим все эти шаги к странице Википедии «List of SpongeBob SquarePants episodes»:  
Цель веб-парсера на C#, который вы собираетесь создать, — автоматически получить все данные об эпизодах со статической страницы Википедии.

Шаг 1: Установите HtmlAgilityPack

HtmlAgilityPack — библиотека C# с открытым исходным кодом, которая позволяет парсить HTML-документы, выбирать элементы из DOM и извлекать из них данные. В принципе, HtmlAgilityPack предлагает все необходимое для веб-парсинга данных статического сайта.  
 
Чтобы установить его, щелкните правой кнопкой мыши на опции «Dependencies» под именем вашего проекта в «Solution Explorer». Затем выберите «Manage NuGet Packages». В окне менеджера пакетов NuGet найдите «HtmlAgilityPack» и нажмите кнопку «Install» в правой части экрана.
 
Во всплывающем окне вас спросят, согласны ли вы внести изменения в ваш проект. Нажмите «OK», чтобы установить HtmlAgilityPack. Теперь вы готовы к выполнению веб-парсинга с помощью C# на статическом сайте.
 
Теперь добавьте следующую строку в верхнюю часть файла App.cs, чтобы импортировать HtmlAgilityPack:  
using HtmlAgilityPack;

Шаг 2: Загрузка веб-страницы

Вы можете подключиться к целевой веб-странице с помощью HtmlAgilityPack следующим образом:
 

// the URL of the target Wikipedia page

string url = "https://en.wikipedia.org/wiki/List_of_SpongeBob_SquarePants_episodes";

var web = new HtmlWeb();

// downloading to the target page

// and parsing its HTML content

var document = web.Load(url);

Экземпляр класса HtmlWeb позволяет загрузить веб-страницу благодаря своему методу Load(). За кулисами этот метод выполняет запрос HTTP GET для получения HTML-документа, связанного с URL, переданным в качестве параметра. Затем Load() возвращает экземпляр HtmlAgilityPack HtmlDocument, который можно использовать для выбора элементов HTML на странице.  

Шаг 3: Выберите элементы HTML

Вы можете выбирать элементы HTML на веб-странице с помощью селекторов XPath. XPath позволяет выбрать один или несколько определенных элементов DOM. Чтобы получить селектор XPath, связанный с элементом HTML, щелкните по нему правой кнопкой мышки, откройте инструменты разработчика в браузере, убедитесь, что он относится к интересующему вас элементу DOM, щелкните по нему правой кнопкой мыши и выберите «Copy XPath».  
 
Цель веб-парсера на C# — извлечь данные, связанные с каждым эпизодом.
 
Помните, что вы хотите выбрать все элементы <tr>. Поэтому необходимо изменить индекс, связанный с элементом select row. То есть, вам не нужно извлекать первую строку таблицы, поскольку она содержит только заголовки таблицы. В XPath индексы начинаются с 1, поэтому вы можете выбрать все элементы <tr> таблицы первого эпизода на странице, добавив синтаксис XPath position()>1.  
 
Кроме того, вы хотите получить данные из таблиц всех сезонов. На странице Википедии таблицы, содержащие данные об эпизодах, находятся со второй по пятнадцатую HTML-таблицу, содержащуюся в HTML-документе. Итак, вот как будет выглядеть окончательная строка XPath:

//*[@id='mw-content-text']/div[1]/table[position()>1 and position()<15]/tbody/tr[position()>1]

Теперь вы можете использовать функцию SelectNodes(), предлагаемую HtmlAgilityPack, чтобы выбрать интересующие вас элементы HTML следующим образом:  
 
var nodes = document.DocumentNode.SelectNodes("//*[@id='mw-content-text']/div[1]/table[position()>1 and position()<15]/tbody/tr[position()>1]");
Обратите внимание, что метод SelectNodes() можно вызвать только для экземпляра HtmlNode. Поэтому вам нужно получить корневой узел HTML-документа с помощью свойства DocumentNode.  
 
Также не забывайте, что селекторы XPath — это лишь один из многих методов выбора элементов HTML на веб-странице. Селекторы CSS — еще один популярный вариант. 

Шаг 4: Извлечение данных из элементов HTML

Во-первых, вам нужен пользовательский класс, в котором будут храниться полученные с помощью веб-парсинга данные. Создайте файл Episode.cs в папке WebScraping и инициализируйте его следующим образом:  
namespace StaticWebScraping {
    public class Episode {
        public string OverallNumber { get; set; }        
        public string Title { get; set; }
        public string Directors { get; set; }
        public string WrittenBy { get; set; }
        public string Released { get; set; }
    }
}
Как вы видите, этот класс имеет четыре атрибута для хранения всей наиболее важной информации об эпизоде. Обратите внимание, что OverallNumber — это строка, потому что номер эпизода в «Губке Бобе» всегда содержит строчный символ.  
 
Теперь вы можете реализовать логику веб-парсинга на C# в вашем файле App.cs, как показано ниже:  
using HtmlAgilityPack;
using System;
using System.Collections.Generic;                        
 
namespace StaticWebScraping {        
    public class Program {
        public static void Main() {
            // the URL of the target Wikipedia page
            string url = "https://en.wikipedia.org/wiki/List_of_SpongeBob_SquarePants_episodes";
 
            var web = new HtmlWeb();
            // downloading to the target page
            // and parsing its HTML content
            var document = web.Load(url);
          
            // selecting the HTML nodes of interest  
            var nodes = document.DocumentNode.SelectNodes("//*[@id='mw-content-text']/div[1]/table[position()>1 and position()<15]/tbody/tr[position()>1]");
            
            // initializing the list of objects that will
            // store the scraped data
            List<Episode> episodes = new List<Episode>();           
            // looping over the nodes 
            // and extract data from them
            foreach (var node in nodes) {