Przeglądać, ściągać i analizować strony internetowe można na wiele sposób dlatego też powstało wiele przydatnych narzędzi które zdecydowanie nam ten proces ułatwiają i tak powstał framework Scrapy

Jak widzieliśmy w równoległym artykule gdzie korzystaliśmy z kilku bibliotek do ściągnięcia danych ze strony

Można realizować to na wiele sposób. Dzięki scrapy, który pozwala nam na tworzenie obiektów spiderów, crawlerów, które są botami wykonywającymi wiele zadań za nas.

W tym przypadku może się wydawać, że jest to proces trudniejszy natomiast jeśli ustawimy sobie już środowisko do wytwarzania takich botów, proces ten staje się wyjątkowo wygodny.

Instalacja

W tym wypadku dobrze, żebyśmy skorzystali ze środowiska uruchomieniowego do Pythona, takiego jak Pycharm.

Tworzymy w nim nowy projekt, po czym w terminalu wykonujemy serie komend instalacyjnych:

pip install scrapy
scrapy startproject nasz_projekt

Dzięki temu framework scrapy stworzy nam strukturę naszego projektu w Pycharm, który będzie zawierać wszystkie potrzebne elementy do realizacji analizy :

Na tym etapie nie musimy dokładnie wiedzieć do czego służą wszystkie te pliki i foldery. Ja nazwałem swój projekt „truecar”, jest to nazwa strony z której będę ściągać dane. To co nas interesuje to folder „spiders”, gdyż tam będziemy pisać naszego „pająka” który będzie chodzić po stronie i zbierać dane.

Stwórz plik o nazwie swojego stworka 🙂 w tym przykładzie będzie to „TruecarSpider.py”, gdyż będziemy ściągać ceny ofert samochodów z portalu do sprzedaży aut używanych o nazwie Truecar.

Budowanie

Rozpoczniemy budowanie naszego Spidera przez stworzenie struktury którą będziemy edytować i dostosowywać do strony z której chcemy pobierać dane.

Do stworzonego przed chwilą pliku w lokalizacji truecar/truecar/spiders/TrueCarSpider.py wklejmy poniższy schemat:

import scrapy

class TruecarSpider(scrapy.Spider):
    name = "truecar"

    def start_requests(self):
       #...

    def parse(self, response):
       #...

W tym projekcie będziemy budować klasę, czyli swój własny obiekt z wybraną przez nas nazwą oraz metodami z których może on korzystać. Moglibyśmy przyrównać to do zmiennej liczbowej INTEGER, która znacie którą możemy dodawać bądź odejmować. Natomiast w tym przykładzie będą to bardziej skomplikowane działania.

W funkcji „start_requests” dodamy ściągnięcie zawartości strony, natomiast w funkcji „parse” będziemy przetwarzać stronę i przygotowywać wynik końcowy.

w zmiennej urls podajemy link do strony z której chcemy pobierać dane oraz budujemy pętlę for, dzięki której możemy w przyszłości podać kilka adresów url w liście według schematu naszego spidera.

    def start_requests(self):
        urls = ["https://www.truecar.com/used-cars-for-sale/listings/tesla/model-3/"]

        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

Kolejnym krokiem jest przetworzenie danych ze ściągniętego materiału zapisanego w zmiennej. Najważniejszym krokiem jest określenie które dane na stronie chcemy przetworzyć.

Znaleźć możemy taki element wciskając prawy klawisz myszy oraz wybierając opcje „zbadaj element” bądź F12 w naszej przeglądarce, Chrome zaznacza nam elementy które przeglądamy.

W kodzie Pythona zapisujemy to w poniższy sposób

def parse(self, response):
        all_listings = response.xpath('//div[@data-qa="Listings"]')

Skąd wzięło się określenie naszej tabeli : (‚//div[@data-qa=”Listings”]’)

Jest to sposób budowania ścieżki to miejsca na stronie, jak widzimy element z danymi który zaznaczam na cała tabele z danymi to :

<div class="margin-top-3" data-qa="Listings">

stąd mamy pierwszy człon DIV następnie [@ nazwę parametru po którym będziemy szukać naszej tabeli czyli „data-qa” oraz jej wartość „Listings”. Stąd powstaje nam wyżej wspomniana ścieżka (‚//div[@data-qa=”Listings”]’). Szczegóły

W kolejnych krokach będziemy oznaczać konkretne informację dla każdego z samochodów które chcemy przetworzyć:

        for tesla in all_listings:

            make_model = tesla.css('div[data-test="vehicleListingCardTitle"] > div')
            year = make_model.css('span.vehicle-card-year::text').get()
            model_raw = make_model.css('span.vehicle-header-make-model text-truncate').get()
            model_raw = str(model_raw)
            model = model_raw[model_raw.find('>')+1:-7].replace('<!-- -->', '')

Przechodzimy ten sam proces co w przypadku pierwszego obiektu całej listy samochodów. W tym wypadku znajdujemy: nazwę modelu (make_model), rok produkcji (year). Następnie w ramach obiektu make_model znajdujemy konkretny model, wykonując działania na zmiennych tekstowych ( http://analityk.edu.pl/python-operacje-na-zmiennych/ )

Następnie budujemy słownik w którym zapisujemy dane dla pierwszego znalezionego modelu oraz zapętlamy proces:

tesla_data = {
                'url' : 'http://truecar.com' + tesla.css('a::attr(href)').get(),
                'model' : str(year) + ' ' + str(model),

                'mileage' : tesla.css('div[data-test="cardContent"] > div > div.text-truncate::text').get(),
                'price' : tesla.css('h4::text').get(),
            }

Podsumowując funkcję parse otrzymujemy następujący stan:

    def parse(self, response):
        all_listings = response.xpath('//div[@data-qa="Listings"]')

        for tesla in all_listings:

            make_model = tesla.css('div[data-test="vehicleListingCardTitle"] > div')
            year = make_model.css('span.vehicle-card-year::text').get()
            model_raw = make_model.css('span.vehicle-header-make-model text-truncate').get()
            model_raw = str(model_raw)
            model = model_raw[model_raw.find('>')+1:-7].replace('<!-- -->', '')

            tesla_data = {
                'url' : 'http://truecar.com' + tesla.css('a::attr(href)').get(),
                'model' : str(year) + ' ' + str(model),

                'mileage' : tesla.css('div[data-test="cardContent"] > div > div.text-truncate::text').get(),
                'price' : tesla.css('h4::text').get(),
            }

            yield tesla_data

Na tym etapie mamy gotowego już naszego stworka i jesteśmy gotowi powiedzieć mu „idź szukaj danych”

Robimy to wykonując prostą komendę w zakładce „terminal” w której podajemy nazwę naszego Spidera, w tym wypadku truecar, która od razu zapisuje nam wszystkie dane w pliku .CSV który podajemy na końcu

scrapy crawl truecar -o truecar.csv

Po wciśnięciu przycisku ENTER nasz stworek zaczyna działać i ściągać dane.

Po zakończeniu jedyne co musimy to otworzyć plik truecar.csv który powstał w naszym folderze z projektem i wybierać wymarzone auto

Podsumowując

Dzięki wzorcowi Scrapy możemy w prosty i u strukturyzowany sposób pobierać dane z dowolnej strony internetowej i zapisywać do pliku .CSV. Największym wyzwaniem jest jedynie określenie odpowiednio selektorów do danych które chcemy ściągnąć. Musimy też pamiętać, że otwarte strony internetowe które nie należą do nas mogą się zmieniać dlatego też trzeba uważnie monitorować działanie naszego stworka i w przypadku braku danych nanieść odpowiednie poprawki.