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ę
Wersja testowana Wydajność Czas pobierania
liczona aut/sec i przetwarzania 4tys aut
Wersja P 4.61 aut/sec 867 sekund ( < 15 min)
Wersja R1 2.93 aut/sec 1365 sekund ( < 23 min)
Wersja R2 4.19 aut/sec 954 sekund ( < 16 min)
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)
Wersja R1
total.time total.pct
getURL 714.08 52.53
strsplit 633.30 46.58
Wersja R2
total.time total.pct
htmlParse 919.01 96.21
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.
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:)
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.
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