Crawlery i scrapery - czym się różnią?

22 grudnia 2022
Jakub Rojek Jakub Rojek
Zdjęcie autorstwa Gregorio Nuti z Unsplash (https://unsplash.com/photos/UBrDZk777tg)
Kategorie: Podstawy IT, Web

Zarówno w zastosowaniach amatorskich, jak i profesjonalnych często zachodzi potrzeba agregowania danych z kilku źródeł. W ten sposób możemy choćby porównywać ceny produktu w różnych sklepach internetowych, wyszukać konkretną rzecz w Internecie, a także uzupełnić informacje na jednej stronie informacjami z drugiej strony. Z pewnością korzystacie z aplikacji i portalów, które w ten sposób zdobywają informacje. Być może także słyszeliście o określeniach "crawler" oraz "scraper" lub o "crawlingu" i "scrapingu". Niektórzy utożsamiają je ze sobą, ale nie powinno się tak robić - te terminy oznaczają różne, choć należące do jednej dziedziny operacje.

Dzisiaj właśnie tym się zajmiemy, tzn. wytłumaczymy sobie, czym jest crawling a czym scraping - różnica jest dość spora, mimo że oba służą jednemu celowi, a mianowicie zautomatyzowaniu przeglądania informacji z innych skrawków Internetu. Tym niemniej odpowiadają innym poziomom wyszukiwania.

Co robią crawlery?

Crawling służy dotarciu do stron w celu np. ich zaindeksowania. Krótko mówiąc - za pomocą crawlera możemy przechodzić przez strony, odkrywając powiązania pomiędzy nimi i prowadzącego do nich linki. To właśnie tutaj najczęściej mówimy o robotach (np. Google'a), które znajdują stronę, sprawdzają, do których innych witryn kieruje przez swoje linki, a następnie podąża dalej. Same podstrony WWW są "czytane" tylko i wyłącznie pod kątem informacji kluczowych do określenia charakteru danej witryny - najczęściej są to metadane, czyli to, co widnieje między tagami <head></head>, ale nie tylko. Tak, jak wspomniałem, crawlera interesują głównie odnośniki prowadzące na inne podstrony, a także symulowanie wyszukiwania elementów tak, jakby robił to człowiek.

O tym, że jest to mechanizm wykorzystywany przez wyszukiwarki już wspomniałem. Natomiast gdzie go można użyć w naszych aplikacjach? Wyobraźcie sobie sytuację, w której robicie porównywarkę cen i musicie znaleźć produkty w wielu sklepach. Macie listę sklepów (np. elektromarketów) i za pomocą crawlera odkrywacie link do konkretnego przedmiotu. Często trzeba również zaimplementować przechodzenie po stronach, aby móc dostać się do konkretnej pozycji. Bardzo często crawlowanie jest wstępem do następnego etapu, który zaraz sobie omówimy.

Co robią scrapery?

Scraping polega na wyszukiwaniu i pobieraniu konkretnych informacji z podstrony. Fachowo nazywa się to ekstrakcją danych. W tym momencie już nie przechodzimy pomiędzy stronami, ale skupiamy się na jednej witrynie i przeglądamy kod HTML pod kątem interesujących nas danych. Czasami jest to dość proste (jeśli twórcy strony dobrze oznaczają specyficzne miejsca za pomocą identyfikatorów lub klas), a czasami wymaga więcej pracy, przygotowania się na różne wersje podstron, dynamiczne doładowywanie elementów itd.

Kontynuując przykład z poprzedniego akapitu - gdy już odnajdziemy linki z produktami, to możemy "zescrapować" z nich informacje o cenie, parametrach technicznych, opis, zdjęcie itd. W ten sposób już ustrukturyzowane dane możemy przenieść do naszej porównywarki cen, gdzie następuje już dalsze przetwarzanie. Oczywiście, dla każdego sklepu musimy mieć osobny scraper (oraz crawler), gdyż każdy ma inaczej przygotowaną stronę WWW, inne położenie elementów, inną konwencję nazewniczą, a czasami także informacje rozlokowane na innych widokach.

Niekiedy crawler i scraper faktycznie stają się jedną aplikacją - dzieje się to najczęściej wówczas, kiedy nie potrzebujemy wielu informacji i możemy je pobrać bezpośrednio z listy produktów. Przykładowo, zdarzyło mi się na swoje potrzeby napisać porównywarkę cen e-booków, przy czym miałem dane wejściowe w postaci książek, które mnie interesują, ale nie chciałem pobierać innych parametrów niż cenę. Jak dobrze wiemy, sklepy internetowe zazwyczaj są skonstruowane w taki sposób, że na liście przedmiotów znajdują się już podstawowe dane pozycji, w tym jego cena. A zatem crawler (potrafiący znaleźć listę zawierającą danego e-booka lub e-booki) stał się jednocześnie scraperem (na liście od razu można było znaleźć cenę e-booka i informacje pozwalające upewnić się, czy to rzeczywiście poszukiwany obiekt).

Do czego i kiedy stosuje się crawling i/lub scraping?

Przede wszystkim te techniki stosuje się w sytuacjach, w których inny sposób integracji jest niemożliwy. Nie da się ukryć, że tam, gdzie jest dostępne API, tam sprawa staje się znacznie łatwiejsza, gdyż jest to dogodniejsza droga do automatycznego pobierania danych, od razu z etykietowanymi wartościami. Niestety, czasem sytuacja wymusza uciekanie się do innych metod, bardziej podobnych do ludzkich zachowań i tutaj przydaje się właśnie crawlowanie oraz scrapowanie.

Przez cały tekst przewija się temat porównywania cen i nie da się ukryć, że to chyba najpopularniejsze zastosowanie takich narzędzi - często chcemy wyszukiwać konkretne informacje w celu podejmowania lepszych decyzji zakupowych, ale o ile dla jednego czy dwóch przedmiotów jest to możliwe w sposób ręczny, o tyle przy kilkudziesięciu produktach sprawa zaczyna robić się trudna do przetworzenia stricte przez człowieka. Co więcej, manualna obsługa zajmuje dużo więcej czasu i może się okazać, że pomiędzy rozpoczęciem a zakończeniem poszukiwań np. ceny ulegną zmianie. Dlatego stosuje się roboty, które pozwalają uzyskiwać te dane w szybszy sposób.

Jednak scrapowanie przydaje się nie tylko do wartości liczbowych. W ten sposób można wydobyć znacznie więcej informacji, jak też choćby komentarze pod artykułami, same treści zgromadzone na stronie czy materiały audiowizualne. Dodatkowo, czasami zależy nam na samym crawlerze, który pozwoli uzyskać bazę linków lub po prostu przeszuka z góry określone strony pod kątem istnienia na niej odpowiednich informacji.

Wreszcie, niekiedy API jest zbyt trudne do użycia lub z jakiegoś powodu niemożliwe jest skorzystanie z niego (np. poprzez dodatkowy sposób weryfikacji). W takich przypadkach scrapowanie stron może być alternatywnym rozwiązaniem, które pozwoli uzyskać przynajmniej część potrzebnych danych. Warto też wspomnieć, że o ile głównym celem scrapowania jest pobieranie informacji, to sam proces może zostać wykorzystany także do analizy struktury strony i wyciągnięcia z tego procesu pewnych danych, które pozwolą przeprowadzić np. badania lub lepiej przygotować bardziej uniwersalne rozwiązania.

Czynniki ryzyka

Nie ma róży bez kolców, a scrapowanie oraz crawlowanie ma bardzo dużo cierni, na które trzeba uważać. Przede wszystkim, jest to technika bardzo wrażliwa na zmiany na stronie. Teoretycznie również zmiana API powoduje konieczność dostosowania się aplikacji, które z niego korzystają, ale w tym przypadku rzadko się zdarza, że zmiany sprawiają, że aktualny klient API nadaje się do kosza i nieczęsto zmienia się np. format przekazywanych informacji z XML na JSON. Natomiast w przypadku zmiany struktury strony WWW scrapery najczęściej trzeba pisać od nowa lub prawie od nowa, gdyż były przygotowane do konkretnej kolejności występowania informacji, zagnieżdżeń itd.

Dodatkowo, scrapowanie i crawlowanie wymagają najczęściej wysyłania licznych żądań HTTP, w większej liczbie niż w przypadku API. Co za tym idzie - nie dość, że transfer danych jest większy, to jeszcze strony, z których robot próbuje odczytać informacje, mogą zidentyfikować danego crawlera jako robota szpiegującego i zablokować go czasowo lub na stałe. Nie dzieje się to często, ale gdy już się stanie, pozyskiwanie informacji staje się niemożliwe. Rozwiązaniami są ograniczenie szybkości pozyskiwania informacji czy wykorzystywanie wielu różnych adresów IP, ale te metody powodują spowolnienie wyszukiwania informacji, a także po prostu mogą nie wystarczyć.

Warto również pamiętać, że te techniki i pisanie scraperów jest po prostu trudne i czasochłonne. Wymagana jest analiza kodu HTML, zaprojektowanie scenariusza, według którego robot będzie "chodził" po stronie, a następnie opracowanie sposobu odkrywania, gdzie znajdują się dane informacje. Tak, jak wspominałem - jeśli twórcy strony WWW dobrze ją opisują, to sprawa staje się znacznie łatwiejsza, ale nie zawsze tak jest, a poza tym samo zasymulowanie pewnych mechanizmów (np. wyszukiwania czy paginacji) jest często trudne. A przypomnijmy sobie, że taką aplikację należy przygotować dla każdej witryny z osobna.

Scrapery i crawlery są też "niepewne" - przy bardzo złej strukturze informacji na stronie czasami po prostu nie można wydobyć danych w zadowalający sposób lub z pewnością stwierdzić, że ta wartość ma być interpretowana w taki, a nie inny sposób. Niestety, takie przypadki się zdarzają i wymagają albo zmiany podejścia, albo większej ilości pracy włożonej w pisanie skryptu, albo wykorzystania metod uczenia maszynowego lub sztucznej inteligencji.

Na koniec warto uświadomić sobie, że wraz z popularyzacją nowoczesnych frameworków JS-owych, zdarza się, że strony nie wczytują całego swojego kodu od razu. Co za tym idzie - robot wchodzący na witrynę może zobaczyć tylko podstawową strukturę, z której nic nie wynika, gdyż reszta danych jest doładowywana w tle. Sprawia to dodatkowe trudności, a niekiedy wręcz uniemożliwia napisanie samego narzędzia. Wówczas trzeba skorzystać z innego podejścia.

W czym pisane są crawlery i scrapery?

Te narzędzia polegają na pobieraniu kodu strony HTML i jego analizie. Najczęściej wiąże się to z wywołaniem jednego żądania typu GET, uzyskaniem jego treści, transformacji jej do drzewa DOM, a następnie przechodzenie po kolejnych stopniach jak przy wyszukiwaniu plików w folderze na komputerze. Informacje najczęściej identyfikuje się po:

  • identyfikatorach lub klasach HTML-owych,
  • kolejności węzłów,
  • stylu przypisanego do poszczególnych tagów (niekiedy tylko taka metoda zostaje),
  • charakteru informacji (np. długości).

Jak widać, potrzebne do tego jest napisanie tzw. parsera DOM lub skorzystanie z gotowych bibliotek, które są dostępne praktycznie w każdym liczącym się języku oprogramowania. Bardzo często jako najlepszy język do pisania crawlerów i scraperów wskazywany jest Python, który oferuje m.in. bibliotekę Beautiful Soup, do którego można znaleźć dużo tutoriali. Python jest językiem, w którym pisze się dość szybko i zawiera sporo rozwiązań dostępnych "na miejscu", co nie jest bez znaczenia zważywszy na fakt, że prędzej czy później crawler lub scraper trzeba będzie i tak napisać od nowa. Natomiast jak najbardziej fani PHP, Javy czy JavaScriptu również znajdą odpowiednie moduły w tych językach, które uprzyjemnią cały proces. Crawlery i scrapery często nie są zbyt dużymi programami, natomiast mogą być dość skomplikowane w zależności od charakteru strony i ilości pozyskiwanych danych.

Istnieje jeszcze drugie podejście, które może się przydać w sytuacji, kiedy strona zawiera dużo elementów dynamicznych i np. użytkownik (a więc także robot, który jest znacznie szybszy od realnej osoby; wręcz za szybki) musi czekać na doładowywanie elementów. W takim wypadku pisanie scrapera w klasyczny sposób może nie zdać egzaminu, gdyż nie uzyskamy interesującego kodu HTML od razu, aby na nim pracować. Zamiast tego można zdecydować się na rozwiązania znane przy pisaniu automatycznych testów akceptacyjnych, z których najpopularniejszy jest Selenium, dostępny zarówno jako wtyczka w przeglądarce, jak i API dla różnych języków programowania. Nie jest to jedyna biblioteka tego typu, jednak nadal może być z powodzeniem wykorzystana do zasymulowania przeglądania strony przez normalnego użytkownika, czekania na pojawienie się informacji oraz pozyskiwania ich.

Podsumowanie

Crawlery i scrapery to małe aplikacje (a może raczej skrypty) pozwalające pobierać informacje lub ich lokalizację i zazwyczaj są pisane z myślą o konkretnych witrynach WWW. Wraz z większą dostępnością API na różnych stronach i otwartością ich twórców, programiści korzystają właśnie częściej z usług sieciowych lub dedykowanych bibliotek, jednak niekiedy nie jest to możliwe i trzeba odczytywać stronę tak, jak robi to człowiek oraz przeglądarka. Warto pamiętać, że z uwagi na dużą zależność od struktury przechowywania informacji na stronie WWW, roboty są bardzo wrażliwe na wszelkie zmiany. Dlatego nie można zakładać, że są niezmienne i posłużą przez cały czas trwania projektu - na szczęście, często są "sprawne" przez dostatecznie długi czas, ale warto pamiętać o tym, aby takie scrapery można było łatwo zamieniać oraz nie uzależniać całego systemu od ich działania.

Pozdrawiam i dziękuję - Jakub Rojek.

Piszemy nie tylko artykuły na blogu, ale też aplikacje i dokumentację dla naszych klientów. Zobacz, z kim do tej pory współpracowaliśmy.

O autorze

Jakub Rojek

Główny programista i współwłaściciel Wilda Software, z wieloletnim doświadczeniem w tworzeniu i rozwoju oprogramowania, ale także w pisaniu tekstów na różnorakich blogach. Zaprawiony w boju analityk i architekt systemów IT. Jednocześnie absolwent Politechniki Poznańskiej i okazjonalny prowadzący zajęcia na tej uczelni. W wolnych chwilach oddaje się graniu w gry wideo (głównie w karcianki), czytaniu książek, oglądaniu futbolu amerykańskiego i e-sportu, odkrywaniu cięższej muzyki oraz wytykaniu innym błędów językowych.

Jakub Rojek