Prosty pająk sieciowy, czyli parsowanie stron internetowych, część 2

Jakiś czas temu we wpisie ,,Prosty pająk sieciowy‘’ (link tutaj) przedstawiłem połączenie skryptu w Perlu i skryptu w R, które wykorzystywałem do zbierania danych o samochodach z serwisu otomoto.pl.

W komentarzach do wpisu użytkownik Maciej opisał podobne rozwiązanie, ale zamiast skryptu w Perlu wykorzystujące pakiet XML (dostępny dla programu R w repozytorium CRAN). Rozwiązanie Maćka ma kilka zalet nad hybryda R+Perl, z mojego punktu widzenia, największa zaleta jest taka, że ,,wszystko’’ dzieje się w R. Łatwiej utrzymać, przenosić i rozwijać rozwiązanie, które jest bardziej jednolite.

Spodziewany koszt tej jednolitości to czasu działania. Wydawało (mi) się, że Perl jako narzędzie do przetwarzania tekstów i działania na stronach internetowych powinien być szybszy od R. Pytanie jaka będzie różnica w czasach działania?

Maciej Beręsewicz przygotował dwa skrypty w R, które wykonują praktycznie te same operacje co mój skrypt w Perlu. Pierwszy skrypt (wersjaStrsplitMB.R) wykorzystuje funkcję getURL() aby ściągnąć źródła strony a następnie używa funkcji strsplit() by wydobyć ze źródła HTML interesujące rzeczy. Drugi skrypt (wersjaXMLMB.R) wykorzystuje funkcję htmlParse() od odczytania i parsowania dokumentu HTML, a następnie xpathApply() do operacji na przetworzonym wstępnie dokumencie. Oba skrypty są dostępne w tym katalogu.

 

Aby porównać czasy działania uruchomiłem te trzy wersje (Perl, R z strsplit i R z XML) kilkukrotnie. Za każdym razem ściągając informacje o 4 tyś aut. Testy rożnych rozwiązań odbyły się na tej samej maszynie, na szerokopasmowym łączu (wykorzystywany tylko jeden węzeł  o wydajności odpowiadającej intel i7). Testy wykonałem o różnych godzinach by zobaczyć jak wpływ na czasy będzie miało natężenie ruchu w sieci, ale koniec końców otrzymałem bardzo powtarzalne wyniki, bez względu na godzinę czy dzień wykonania testów. Więc niżej pokażę tylko medianowe wyniki  z różnych uruchomień.

Porównywane wersje:

  • Wersja P = Perl + wczytanie danych do R
  • Wersja R1 = R ściąganie getURL() i parsowanie z użyciem funkcji strsplit()
  • Wersja R2 = R ściąganie i parsowanie z użyciem funkcji htmlParse()

Medianowe czasy działań i odpowiadająca im wydajność liczna w liczbie ,,przetworzonych’ ‚stron opisujących kolejne auta na sekundę

 

 

Ponieważ profilowanie kodu w R jest cudownie proste sprawdziłem też, które elementy ,,zżerają’’ najwięcej czasu w obu wersja Rowych. Poniżej wyniki dla medianowego czasu działania (tylko operacje najbardziej czasochłonne)

W wersji R1, ponad 99% czasu zużyte jest te dwie operacje. Dodatkowy narzut związany z pętlami, zapisywaniem na dysku itp to mniej niż 1%. Z tych dwóch operacji mniej więcej tyle samo czasu trwa odczytywanie HTML przez sieć co jego parsowanie.

W wersji R2 większość czasu przetwarzania to wywołanie htmlParse(), która jest opakowaniem odwołania do funkcji napisanej w C.

 

Pointa?

Wersja perlowa jest najszybsza, ale wersja używająca pakietu XML jest niewiele wolniejsza. Biorąc pod uwagę dodatkowo długość kodu, jednolitość bardziej podoba mi się rozwiązanie Macka używające pakietu XML.

 

3 thoughts on “Prosty pająk sieciowy, czyli parsowanie stron internetowych, część 2”

  1. Przyznam szczerze, że nie spodziewałem się takiego fajnego wyniku, zwłaszcza w przypadku pakietu XML. Na moim komputerze tak szybko to nie działa:)

  2. Hej, jestem trochę raczkujący w tej dziedzinie – jak mogę przetestować te skrypty? Co muszę mieć zainstalowane?
    Będę wdzięczny za krótki manual – wydaje się to być mega przydatne i chciałbym coś takiego sobie przenieść na strony z mieszkaniami.

  3. Zacznij od pakietu XML, RCurl i httr. Pakiet XML wymaga znajomości języka XML oraz XPath (w3schools będzie pomocne).

    Możesz rozpocząć od:
    url<-'www.otodom.pl'
    doc<-htmlParse(url, encoding='utf-8')

    a później funkcją xpathApply lub xpathSApply wyciągasz odpowiednie elementy strony. Należy sprawdzić to klikając na dany element strony i sprawdź źródło.

    Pozdro,
    MB

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *