Время прочтения: 4 мин.
Для задач по анализу данных необходимо большое количество информации, которая может быть недоступна или отсутствовать на внутренних ресурсах организации, и для их решения необходимо обратиться к другим источникам, например, внешним ресурсам данных. Как правило, внешние ресурсы не предоставляют возможностей для выгрузки информации одним списком, и для получения данных необходимо выполнить некоторое количество действий на сайте – заполнить форму, нажать кнопку, выбрать категорию, подкатегорию и т.д.
Такой способ не подходит для обработки больших массивов данных, например, получение данных об организациях по списку ИНН. Чтобы ускорить (процесс выгрузки) мы можем применить библиотеку Selenium — инструмент для автоматизации тестирования веб-приложений.
Библиотека позволяет взаимодействовать со страницей так, как будто эти действия выполняются обычным пользователем: ввести данные в поле, перейти по ссылке, переключиться между вкладками и другие действия.
Библиотека поддерживает работу с различными браузерами: Firefox, Safari, Chrome, Edge, IE.
Для того чтобы библиотека могла взаимодействовать с браузером необходимо иметь на компьютере драйвер, соответствующий версии браузера.
Подробнее остановимся на основных возможностях библиотеки при работе с браузером Chrome.
При запуске экземпляра браузера есть возможность задать аргументы командной строки с помощью метода AddArgument() класса ChromeOptions, например отключить графический интерфейс или задать параметры для HttpRequest:
var opt = new ChromeOptions();
opt.AddArgument("--no-sandbox");
opt.AddArgument("--disable-gpu");
opt.AddArgument("--headless");
opt.AddArgument("--disable-automation");
var walker = new ChromeDriver(path, opt);
Загрузка страницы и навигация осуществляются через интерфейс INavigation.
С помощью метода GoToUrl(string url) осуществляется переход на страницу, метод Back() возвращает предыдущую страницу браузера, а метод Forward() – следующую.
После того как будет осуществлен переход на страницу, с помощью объекта драйвера можно вернуть html-код страницы через свойство PageSource, вернуть адрес страницы через свойство Url или найти элемент на странице.
Для поиска элемента на странице у класса ChromeDriver есть несколько специализированных методов, напимер, FindElementByClassName(string class) ищет на странице элемент с заданным классом.
Также можно воспользоваться общими методами FindElement(By by) и FindElements(By by).
Параметр этих методов – класс By предоставляет свои методы, определяющие по каким признакам будет производиться поиск элемента, например:
var paragraph = walker.FindElement(By.TagName(“h”));
вернет первый элемент <h> на странице,
var paragraphs = walker.FindElements(By.TagName(“h”));
вернет все элементы <h> в списке.
В некоторых случаях на странице может быть не обнаружен элемент, хотя при визуальном просмотре страницы он есть. Это означает что элемент был добавлен на страницу при помощи js-скрипта, который не успел отработать до того, как был вызван метод поиска элемента.
Чтобы избежать подобных случаев можно воспользоваться двумя способами:
- Установить свойство драйвера ImplicitWait, время, в течении которого драйвер будет бездействовать после перехода на страницу:
walker.Manage().timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
- Использовать класс WebDriverWait. Класс позволяет с указанной периодичностью проверять страницу пока указанный элемент не будет найден:
var element = new WebDriverWait(walker, TimeSpan.FromSeconds(5)).until(x => x.FindElement(By.Id(“someID”))));
Для взаимодействия с элементом используются методы интерфейса IWebElement.
Нажатие на кнопку имитирует метод Click(), ввод пользователя – метод SendKeys()
Представленный ниже код имитирует ввод пользователем своего логина/пароля и нажатие на кнопку авторизации:
var loginElem = new WebDriverWait(driver, 10).Until(
x => x.FindElement(By.Id(“username”)));
var pwdElem = new WebDriverWait(driver, 10).Until(
x => x.FindElement(By.Id(“password”)));
var submitElem = new WebDriverWait(driver, 10).Until(
x => x.FindElement(By.Id(“submit”)));
loginElem.SendKeys(user);
pwdElem.SendKeys(pwd);
submitElem.Click();
C помощью класса Actions можно задавать и выполнять цепочки действий. В конструктор передается экземпляр драйвера, методы задают действия которые необходимо выполнить и затем запускается выполнение цепочки методом Perform():
New Actions(walker).SendKeys(loginElem, “username”).SendKeys(pwdElem, “password”).Click(submitElem).Perform();
Мы использовали эту библиотеку для получения информации о дате регистрации ОГРН для списка ИНН организации, ниже приведен код нашего решения:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace MyApp
{
class Program
{
public static Dictionary<string, string> GetDateFromEGRUL(List<string> inns)
{
var path = "path/to/cromedriver";
var url = "https://EGRUL.url";
var innDates = new Dictionary<string, string>();
foreach (var inn in inns)
{
var opt = new ChromeOptions();
opt.AddArgument("--no-sandbox");
opt.AddArgument("--disable-gpu");
opt.AddArgument("--headless");
opt.AddArgument("--disable-automation");
var walker = new ChromeDriver(path, opt);
walker.Navigate().GoToUrl(url);
var innInput = new WebDriverWait(walker, TimeSpan.FromSeconds(5))
.Until(x => x.FindElement(By.Id("query")));
var findBtn = new WebDriverWait(walker, TimeSpan.FromSeconds(5))
.Until(x => x.FindElement(By.Id("btnSearch")));
new Actions(walker)
.SendKeys(innInput, inn)
.Click(findBtn)
.Perform();
var date = walker
.FindElement(By.XPath("/html/body/div[1]/div[3]/div/div[1]/div[4]/div/div[3]/div"))
.Text
.Split("ОГРНИП: ")
.ToList()
.Last();
innDates.Add(inn, date);
}
return innDates;
}
static void Main(string[] args)
{
List<string> data = LoadInnFromFile("path/to/inn/file.csv");
SaveDatesToFile(GetDateFromEGRUL(data));
}
}
}
Преимущество библиотеки Selenium – в возможности полностью повторить и автоматизировать действия пользователя на любом сайте, недостаток – довольно медленная работа библиотеки, связанная с тем что при переходе на страницу необходимо дожидаться ее полной загрузки.
Во время работы с библиотекой мы получили интересный опыт по добыче информации из внешних источников и снизили трудозатраты на выполнение этой операции. Предлагаем всем использовать представленный инструмент и делиться своим опытом.