800px-Mucha-jobdzisiejszy wpis jest przygotowany gościnnie przez Kacpra. Kacper jest specjalistą SCCM i szeroko rozumianej automatyzacji/orkiestracji, co tłumaczy odwołanie się do metod zakrawających na developerkę, gdy UI w postaci formatek dostarczanych przez dostawcę nie wystarczyło. jest to też bardzo ciekawy przykład tego, jak uniwersalny jest PS…

.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.

Nie znasz dnia, ani godziny kiedy może się przydać PowerShell. Szukałem ostatnio lodówki z kostkarką i trafiłem w ten sposób na stronę w http://www.liebherr.aged.com.pl/. Niestety twórca filtra produktów nie przewidzał, że ktoś mógłby szukać lodówki ze wspomnianą kostkarką. Mogłem oczywiście znaleźć sobie jakąś inną stronę czy sklep internetowy. Jednak mój wewnętrzny nerd został podrażniony, nie było już odwrotu. :) Postanowiłem zaprząc PowerShella do tego zadania, jak to mam w zwyczaju. Trzeba było napisać małego crawlera, który znajdzie to czego mi się nie chciało samemu szukać. Efektem postanowienia jest poniższy skrypt:

$rootUris = 'http://www.liebherr.aged.com.pl/produkty/urzadzenia-domowe/side-by-side-i-frenchdoor/', 'http://www.liebherr.aged.com.pl/produkty/urzadzenia-domowe/zamrazarki/', 'http://www.liebherr.aged.com.pl/produkty/urzadzenia-domowe/chlodziarko-zamrazarki/', 'http://www.liebherr.aged.com.pl/produkty/urzadzenia-domowe/chlodziarko-zamrazarki-do-zabudowy/'

$rootUris | ForEach-Object {
    $rootUri = $_
    $response = Invoke-WebRequest -Uri $rootUri
    $links = ($response.Links | Where-Object href -match '.html').href | Sort-Object -Unique

    $urisArray = @()
    $links | %{
        $uriResponse = Invoke-WebRequest -Uri $_
        $urisArray += $uriResponse.RawContent
    }

    Write-Host $rootUri -ForegroundColor Green
    $features = 'Ice Center', 'IceCenter', 'IceMaker'
    $regex = '(?i)<title[^>]*>(.*)</title>'
    $features | ForEach-Object {
        $feature = $_
        
        $urisArray | Where-Object {$_ -match $feature} | ForEach-Object {
            $content = $_
            $result = [Regex]::Matches($content, $regex)
            $result | ForEach-Object {
                "$($feature): $($_.Groups[1].Value)"
            }
        }
        
        #$urisArray | Where-Object {$_ -match $feature} | Select-String -Pattern "<title>.*<\/title>" | %{"$($feature): $($_.Matches.Value)"}
    }
}

O dwóch rzeczach należy wspomnieć. Cmdlet Invoke-WebRequest i wykomentowanej linii na końcu. Invoke-WebRequest wywołuje uczucia ambiwalentne. Z jednej strony ma kilka fajnych funkcjonalności jak np. użyta właściwość Links zwracanego obiektu. Zawiera ona tablicę linków które znajdują się na stronie, więc nie trzeba się bawić w regexy i szukać ich samodzielnie. Jest też kilka innych ciekawych właściwości jak np. Images czy InputFields. niestety Invoke-WebRequest ma też jedną wadę, która może być w pewnych sytuacja dosyć uciążliwa. Mianowicie dosyć słabo sobie radzi z kodowaniem UTF8 bez BOMa. A w zasadzie to w ogóle sobie nie radzi i zwraca po prostu krzaki jeśli na stronie są np. polskie znaki diaktryczne. I niestety nic się nie da z tym zrobić w zasadzie, a przynajmniej mi się nie udało. Jako obejście można skorzystać z klas .NET Net.WebRequest i Net.WebResponse, ale tracimy wtedy opisane wcześniej zalety Invoke-WebRequesta.

Natomiast wykomentowana linia to pierwsza wersja pętli, która znajduje się bezpośrednio nad nią. Korzystając z Select-Stringa nie da się pobrać zawartości znacznika title, bez samego znacznika. Ponownie trzeba się odwołać do klasy .NET Regex, która zwraca grupy dopasowań, a dzięki nim mamy także dostęp do samej zawartości znacznika.

Kacper.

.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.

eN.

-o((:: sprEad the l0ve ::))o-

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Time limit is exhausted. Please reload CAPTCHA.