Наверняка вы ежедневно проглядываете излюбленные сайты Интернета, чтобы узнать, что происходит в мире. Вы заходите на Twitter, смотрите погоду, читаете новости и т. д. Существуют агрегаторы новостей (вспомним RSS), но иногда было бы неплохо собрать в одном месте информацию с различных веб-сайтов. Обязательно ли для этого уметь программировать? Лишь самую малость, и это совсем просто, если воспользоваться командой Invoke-WebRequest.

Сейчас я нахожусь вблизи местечка Дак в Северной Каролине, в нескольких минутах езды от моря. Как мне помощью Invoke-Webrequest узнать, скажем, температуру воды? Армейский корпус инженеров ведет сайт сбора данных Field Research Facility (FRF), где, помимо прочего, сообщается и температура воды, ее можно увидеть на домашней странице в левом верхнем углу. Эти данные мы и возьмем для примера (см. экран).

 

Сайт сбора данных о температуре воды
Экран. Сайт сбора данных о температуре воды

Загрузка страницы

Чтобы загрузить страницу и, находясь на ней, сохранить ее в переменную, которую мы назовем $webpage, введем команду:

$webpage=Invoke-webrequest www.frf.usace.army.mil

Подав результат выполнения этой команды по конвейеру на вход Get-Member (что всегда полезно, когда впервые имеешь дело с новым существительным-объектом PowerShell), мы увидим, что команда Invoke-WebRequest разбивает страницу на куски: $webpage.images — для вывода списка загруженных изображений; $webpage.headers — информация заголовка;. forms и. inputfields — пустые разделы, так как наша домашняя страница не имеет форм. Затем. links — все гиперссылки, имеющиеся на странице, а также. content и. rawcontent — код HTML. Исходя из предположения, что у нас есть папка C:\scripts, сохраняем содержимое в текстовый файл:

$webpage.RawContent | Out-File "c:\scripts\webpage.txt" ASCII
   -Width 9999

либо копируем в буфер и вставляем в блокнот:

$webpage|clip.exe

Анализ текста

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

Начинаем анализ текста домашней страницы. Можно догадаться, что Pier End встречается на странице только один раз. Поиск в «Блокноте» подтверждает, что эта запись действительно имеется только в одном месте в следующей строке HTML-кода:

Water Temp Pier End 21° C    70° F

После быстрого подсчета устанавливаем, что интересующие нас две цифры начинаются через 45 символов после Pier End. Таким образом, последовательность действий выглядит следующим образом:

  • пропустить весь текст, предшествующий Pier End;
  • отступить на 45 символов вперед от этой записи;
  • запомнить следующие два символа;
  • все остальное пропустить.

Эту схему в PowerShell можно реализовать с использованием регулярного выражения — regular expression или regex. PowerShell находит каждое вхождение некоего текстового фрагмента и заменяет его другим текстом. Например, заменить Pier на Dock по всей строке можно с помощью запроса:

PS C:\scripts> $a="Pierdockpierdock"
PS C:\scripts> $a -replace "pier","dock"
Dockdockdockdock

Необычная запись -replace заставляет думать, что здесь строковая переменная получает параметр команды или что-либо еще, но таков уж синтаксис. Если же говорить о необычном, то приготовьтесь познакомиться с синтаксисом регулярного выражения. При всех своих достоинствах этот инструмент выглядит невероятно.

  • «Пропустить весь текст до Pier End» записывается так: [\S\s]*Pier End. Здесь [\S\s] означает «все, что угодно», а звездочка (*) означает «столько, сколько будет найдено». Pier End означает просто Pier End.
  • «Отступить 45 символов» записывается так. {45}. Точка (.) означает любой символ, кроме конца строки, а {45} указывает, что число символов равно 45 (в противоположность звездочке, означающей «сколько угодно»).
  • «Запомнить следующие два символа» записывается так: (\d\d). Круглые скобки предписывают запомнить в переменную $1, а \d означает «любая цифра». Таким же образом будет работать выражение (\d{2}).
  • В завершение пишем [\S\s]*, чтобы пропустить все, что осталось. Итак, запрос на извлечение температуры воды выглядит следующим образом:
   $webpage= (Invoke-WebRequest www.frf.usace.army.mil).rawcontent
   $webpage -replace"[\S\s]* Pier End.{45} (\d\d) [\S\s]*",'$1'

Это был всего лишь первый опыт, и наше регулярное выражение вышло несколько неуклюжим, но все же позволило решить задачу. В следующей статье мы продолжим тему сбора данных из Интернета и знакомство с регулярными выражениями.