Поиск по сайту:

Использование AngleSharp в PowerShell 7 для анализа веб-страниц


AngleSharp — это библиотека .NET, которая упрощает и ускоряет синтаксический анализ содержимого HTML и работу с ним. Поскольку AngleSharp написан на .NET, вы также можете использовать выходные данные в PowerShell. Сочетание этих двух элементов позволяет быстро и легко создавать сценарии HTML-содержимого. В этой статье мы рассмотрим, как настроить AngleSharp и использовать страницу погоды, а также преобразовать данные в объект PowerShell.

Установка и загрузка AngleSharp

Установить AngleSharp легко с помощью команды Install-Package. Вы даже можете установить пакет в область CurrentUser, что означает, что вам не нужны права администратора для использования этой библиотеки. Пакет содержится в библиотеке NuGet.

Install-Package 'AngleSharp' -Scope 'CurrentUser' -Source 'Nuget'

Далее нам нужно загрузить AngleSharp для использования в нашем скрипте PowerShell. Для этого мы будем использовать командлет Add-Type, чтобы напрямую загрузить DLL для библиотеки. Ниже приведен код, который помогает найти последнюю версию .NET и загрузить этот путь, если библиотека еще не загружена в вашем сеансе.

If ( -Not ([System.Management.Automation.PSTypeName]'AngleSharp.Parser.Html.HtmlParser').Type ) {
    $standardAssemblyFullPath = (Get-ChildItem -Filter '*.dll' -Recurse (Split-Path (Get-Package -Name 'AngleSharp').Source)).FullName | Where-Object {$_ -Like "*standard*"} | Select-Object -Last 1

    Add-Type -Path $standardAssemblyFullPath -ErrorAction 'SilentlyContinue'
} # Terminate If - Not Loaded

Читайте дальше, чтобы узнать, как проанализировать содержимое веб-страницы и создать полезный объект PowerShell!

Разбор веб-страницы

Конечно, весь смысл этого заключается в том, чтобы фактически проанализировать веб-страницу. В этом примере мы загрузим содержимое из Invoke-WebRequest, а затем, используя результат, проанализируем содержимое в AngleSharp. Мы собираемся использовать местный 7-дневный прогноз от Национальной метеорологической службы, чтобы получить данные о погоде и преобразовать их в объект. Во-первых, давайте получим данные о погоде.

$Request = Invoke-WebRequest -Uri "<https://forecast.weather.gov/MapClick.php?lat=40.48675500000007&lon=-88.99177999999995>"

Данные для интересующего нас сайта находятся в свойстве Content, но это полный исходный HTML-код, который требует большой обработки. Часто проще всего использовать инструменты разработчика Chrome, чтобы найти раздел исходного HTML-кода, который мы хотим использовать (F12 в Chrome для сайта, который вы хотите проверить).

Структура HTML страницы погоды NWS.

К счастью, есть контейнер div с неупорядоченным списком, который мы можем анализировать. Следующим шагом является фактическая загрузка полученного контента в AngleSharp.

$Parser = New-Object AngleSharp.Html.Parser.HtmlParser
$Parsed = $Parser.ParseDocument($Request.Content)

Теперь, когда у нас есть проанализированный контент, доступный в нашей переменной $Parsed, мы можем начать манипулировать этими данными, чтобы добраться только до нужного раздела. Очень удобно, что сайт NWS предоставляет идентификатор только для этого ненумерованного списка с именем семидневный-прогноз-список. Поскольку каждый идентификатор на HTML-странице уникален, это упрощает нацеливание на список. Используя свойство All нашего проанализированного контента, мы можем получить только объект с идентификатором seven-day-forecast-list.

$ForecastList = $Parsed.All | Where-Object ID -EQ 'seven-day-forecast-list'

Это приведет к множеству различных свойств, но мы сосредоточимся на свойстве ChildNodes, так как оно будет содержать каждый li, содержащий нужные нам данные. Чтобы получить представление о том, что мы ищем в нашем объекте, давайте взглянем на отдельный li. Есть несколько элементов с классами, на которые мы можем ориентироваться.

  • имя-периода — относительный период времени.
  • short-desc — краткое описание погоды.
  • temp temp-high — высокая температура.

HTML-структура одного элемента-контейнера-захоронения.

Вы могли заметить, что тег img содержит свойство alt с большим количеством полезной информации. Довольно легко найти целевой класс, поскольку он хранится в свойстве classname дочернего узла. Чтобы настроить таргетинг на элемент alt, нам придется полагаться на немного другой метод, QuerySelectorAll, который использует традиционные селекторы CSS для упрощения сложного таргетинга.

$ForecastList.ChildNodes | ForEach-Object {
	# Retrieve just the content of the tombstone-container div underneath the forecast-tombstone li element.
  $Node = $_.ChildNodes | Where-Object ClassName -EQ 'tombstone-container'

  [PSCustomObject]@{
		# Search the child nodes under the tombstone-container and find the element named period-name. Retrieve just the innerHTML which is the text value. This includes a break element, <br> of which we don't need, so replace that with a space instead.
    "Period" = $Node.ChildNodes.Where({ $_.ClassName -EQ 'period-name'}).InnerHTML -Replace "<br>"," "
    "Temp"   = $Node.ChildNodes.Where({ $_.ClassName -Match 'temp'}).InnerHTML
    "Short"  = $Node.ChildNodes.Where({ $_.ClassName -EQ 'short-desc'}).InnerHTML -Replace "<br>"," "
		# Since we don't have a class to target, on the root node, use the CSS selector p > img which looks for a p element with a child img element. Next, use the Attributes property to find the one named alt and return it's value.
    "Alt"    = $Node.QuerySelectorAll("p > img").Attributes.Where({$_.Name -EQ 'alt'}).Value
  }
}

Вывод проанализированной веб-страницы из AngleSharp.

Хотя нам нужно перебрать несколько элементов, чтобы в конечном итоге получить только те, которые нам нужны, мы можем пройтись по структуре HTML-документа и получить именно то, что нам нужно. Может быть немного сложно понять структуры, но в конечном счете AngleSharp создает объекты для каждого элемента DOM. Как только вы найдете лучший способ нацеливания на нужные вам элементы, извлечение контента не составит труда.

Заключение

AngleSharp предлагает отличный программный интерфейс для анализа и взаимодействия с HTML-контентом на веб-страницах. Это может открыть дверь для использования PowerShell для извлечения содержимого, которое иначе может быть недоступно. Получение этого содержимого, его сохранение и использование в сценариях чрезвычайно полезно и может помочь в методах системной интеграции!