PowerShell. Парсинг сайта или забрать значение с сайта.

Иногда при выполнении скрипта приходится опираться на значения с web сайтов. В PowerShell с версии 3.0 для этого имеется замечательный командлет Invoke-WebRequest.

Рассмотрим подробнее скрипт:

!!!В строчке $trash = $li.innerhtml -match " \ ( ( . * ? ) \ ) " убрать пробелы внутри ковычек » \ ( ( . * ? ) \ ) «.!!!

Этот скрипт выполняет следующие действие: на сайте «http://coolcode.ru» мы находим рубрику «Администрирование» и смотрим сколько в данной рубрике статей.

В начале мы создаём объект, со страницей сайта:

Здесь используется самая главный командлет Invoke-WebRequest

В данном примере мы используем только необходимые параметры:

-Uri <String>

Командлет Invoke-WebRequest поддерживает следущие протоколы: HTTP, HTTPS, FTP, и FILE.  В данном параметре необходимо указать url к странице, в нашем случае это http://coolcode.ru’.

-Method <WebRequestMethod>

Определяет метод используемый для веб-запроса. Допустимые значения: Default, Delete, Get, Head, Merge, Options, Patch, Post, Put и Trace.

Пробежимся в крации по ним:

Head Получение заголовка, без тела. В основном используется для получения матаданных.

Get Применяется для получения содержимого указанного ресурса.

Options Применяется для определения возможностей веб-сервера или параметров соединения.

Post Используется для передачи данных на сервер.

Put Загрузка содержимого на указанный uri.

Patch Тоже самое, что и Put но только применяется на фрагмент ресурса

Delete Удаляет указанный ресурс.

Тrace Возвращает полученный запрос, с информацией о добавлении и изменении запроса промежуточными серверами.

Merge

В своём примере я использую значение POST. Хоть мне надо всего лишь получить данные из тела страницы и в первой редакции этой статьи я использовал метод GET, но с методом GET как то через раз отрабатывал параметр -contentType.

 -ContentType <String>

Задаёт тип содержимого в веб-запросе. по умолчанию «application/x-www-form-urlencoded». Я использую данный метод, для получения данных в правильной кодировке :-ContentType «text/plain; charset=utf-8». У меня почему то этот параметр через раз работал с «-Method GET», после изменения на «-Method POST» всё работает корректно.

У командлета Invoke-WebRequest существуют так же ещё много интересных параметров, которые могут быть вам интересны:

-Body<Object>

Данный параметр задаёт тело запроса, и используется для заполнения полей на сайте. (этот параметр  рассмотрим в другой статье)

-Certificate<X509Certificate>

Задаёт сертификат, для реализации безопасности в веб-запросе. Что бы найти сертификат воспользуйтесь командлетом Get-PfxCertificate или используйте Get-ChieldItem на диске Cert:. Если сертификат не действительный или не имеет достаточных полномочий, команда не выполнится.

-CertificateThumbprint<String>

Задаёт учётную запись пользователя, который имеет право на отправку запроса на цифровой сертификат открытого ключа (X509).

-Credential<PSCredential>

Задаёт учётную запись пользователя, который имеет разрешение на отправку запроса. По умолчанию используется текущий пользователь.

-DisableKeepAlive

Устанавливает значение постоянного HTTP соединения в HTTP-заголовке в значение False. По умолчанию постоянное HTTP соединение включено.

-Headers<IDictionary>

Устанавливает заголовок веб-запроса. Можно указать хэш-таблицу или словарь.

-InFile<String>

Получение содержимого веб-запроса из файла.

Определяет, сколько раз Windows PowerShell может совершить попыток для соединение с заданным URI, прежде чем возникнет ошибка подключения. По умолчанию значение 5. Значение 0 блокирует все попытки.

-OutFile<String>

Сохраняет тело ответа в указанный файл.

-PassThru

Возвращает результаты в консоль, в дополнении к записи результатов в файл. Используется вместе с параметром -OutFile

-Proxy<Uri>

Задаёт прокси сервер для выполнения запроса.

-ProxyCredential<PSCredential>

Параметры учётной записи для прокси. Например «User01» или «Domain01\User01».

-ProxyUseDefaultCredentials

Для соединением с прокси использовать учётные данные текущего пользователя.

-SessionVariable<String>

Создаёт сеанс веб-запроса в и сохраняет его в значение указанной переменной. Переменную необходимо вводить без знака доллара «$». При указании переменной сеанса, Invoke-WebRequest создаёт объект сеанса веб-запроса и присваивает его переменной с указанным именем. Вы сможете использовать данную переменную, как только закончится выполнение запроса. Данный объект не является постоянным соединением. Он содержит информацию о связи запроса, кукисы, учётные данные, максимальные значения количества соединений и строки агента пользователя. Этот объект можно использовать для обмена состояниями данных, между веб-запросами.

-TimeoutSec<Int32>

Данный параметр задаёт время, в течении которого запрос может находится в ожидании. Время указывается в секундах. Значение по умолчанию 0, что укзывает на неопределённый тайм-аут(сколько угодно долгий).

-TransferEncoding<String>

Определяет значение зжатия для заголовка HTTP. Допустимы значения Chunked, Compress, Deflate, GZip и Identity.

-UseBasicParsing

Использование объекта ответа для HTML без синтаксического анализа DOM.

-UseDefaultCredentials

Использование учётных данных текущего пользователя, для отправки веб-запроса.

-UserAgent<String>

Использовать строку для аутентификации сайтом агента. По умолчанию используется «Mozilla/5.0 (Windows NT; Windows NT 6.1; en-US) WindowsPowerShell/3.0».

-WebSession<WebRequestSession>

Назначает сеанс веб-запроса.  Переменная указывается со знаком доллора($).

Что бы изменить значение параметров в сеансе веб, используйте параметры командлета, например UserAgent или Credential. Параметры командлета имеют больший приоритет, чем значчения в сессии веб-запроса.

В полученной переменной будет содержаться информация о

 

После исполнения команды

У будет объект, содержащий данные страницы http://coolcode.ru, но это не просто текст, а как и всё в PowerShell это объект. И у него есть очень интересные свойства:

Рассмотрим их:

AllElements — Возвращает массив свойств всех элементов.
Forms — Возвращает массив свойств всех форм.
Images — Возвращает массив всех свойств изображений.
InputFields — Возвращает массив всех свойств полей воода.
Links — Возвращает массив свойств ссылок.
ParsedHtml — Возвращает странцу ввиде дерева объектов.
Scripts — Возвращает массив свойств всех скриптов.

Content — Возвращает содержимое страницы.

 

И переходим к следующей строчке скрипта:

 

В моём случае я использую свойство AllElements объекта $ie . И у меня получится массив элементов страницы … каждый элемент будет являтся объектов со следующими свойствами:

Рассмотрим его свойства:

tagName — имя элемента (div,li,p,a…)
innerHTML — HTML код внутри тэга.
innerText — Отображаемый код из тега.
outerHTML  — Код всего тэга.
outerText — текс который отображается из этого тэга.

 

В нашем примере я использую  свойства tagName и innerHTML которые должны равнятся соответствующим значениям:

как я узнал каким значениям должны ровняться данные параметры?

Я посмотрел код страницы. В Chrome и Firefox например, можно выделить интересующий вас участок и нажав правую кнопку выбрать в выпадающем списке кнопку звучащую примерно, как «Просмотреть код».

Но вернёмся к скрипту. После отработки строчки:

в переменной $li у нас будет содержаться код тэга li с кодом внутри содержащим слово «Администрирование».

Теперь из него осталось достать нужную нам информацию… а конкретно значение в скобках. Я предлагаю воспользоваться регулярным выражением:

!!!В строчке $trash = $li.innerhtml -match " \ ( ( . * ? ) \ ) " убрать пробелы внутри ковычек » \ ( ( . * ? ) \ ) «.!!!

Нужное нам значение получено.

Комментарии:

Комментарии 5

  • Добрый день!
    Снова немного столкнулся с парсингом html и вернулся сюда, а тут бах и сюрприз PowerShell !!!
    За что Вам огромнейшее спасибо.
    Но есть вопросик.
    Я использую PowerShell 5.0.10586.117 (запускал из ISE) и у меня данный код отработал, но сначала вылезло сообщение «Предупреждение системы безопасности Windows», я сменил название рубрики с Администрирование на Скрипты, но число всё равно выводил 16.
    Закрыл ISE и проверил заново, в итоге получаю тоже «Предупреждение системы безопасности Windows», а за тем:
    Vector smash protection is enabled.
    Cannot index into a null array.
    At E:\Scripts\PowerShell\Parser.ps1:4 char:1
    + $Matches[1]
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

    • Как не странно, но всё правильно.
      в обоих случаях мы находим следующий li:

      То есть «скрипты» это под категория раздела «администрирования»… а я вывожу первое значение с цифорками из раздела.

      Про ошибку…. всё дело в кодировке.

      У меня какой то косячный сайт (WordPress из коробки :), PowerShell раз в несколько десятков раз отображает кодировку правильно, и очень вероятно, в первый раз тоже она окажется правильной. %)

      после чего массив $Matches заполняется и при повторном запуске не изменяется.
      При этом браузеры отрабатывают корректно.
      Попытался конвертировать вывод, но ничего не получилось… попытался поиграться с -ContentType вообще 0 реакции.
      убил 3 часа… идей нет …

      • Хотя нет, идеи есть… Изменил метод с GET на POST. Вроде начал отрабатывать -ContentType. по крайней мере у меня кодировка стабильно корректная :).

  • Некоторый сайты, требуют обязательного параметра -UseBasicParsing, например:
    $r = Invoke-WebRequest "http://ivolgann.com" -Method Post -UseBasicParsing -ContentType "text/plain; charset=utf-8"
    $r.links

  • Антон, приветствую, хотел поинтересоваться, есть ли возможность впихнуть в GUI тело на Powershell js скрипт, который использует сайт?

    Есть внутриорганизационный справочник, содержащий телефонную базу, доступ к этой базе с сайта осуществляется через js скрипт, набирая первые цифры внутреннего номера пользователь получает список с информацией о номере, переходя открывается новая страница браузера содержащуюю эту информацию в расширенном виде. Хотел внедрить такое же решение в guiшку на powershell добавить textbox который так же будет переваривать эту функцию как сайт? может .. можно не внедряя js в ps скрипт, осуществлять реализацию этой функции через инфу, которую можно получить со страницы сайта.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *