Vehicleanalizer.com — tracker cen ogłoszeń motoryzacyjnych z OLX i Otomoto

Aplikacja, która codziennie zaciąga ogłoszenia samochodów z portali, rysuje wykresy cen, rocznika i przebiegu oraz pilnuje, kiedy sprzedawca kombinuje przy cenie.

JAJarosław Armatys 7 min czytania
Wersja wideo tego wpisu — obejrzyj na YouTube

Problem — kupujesz auto, ale ile ono realnie kosztuje

Każdy, kto próbował kupić używane auto, zna ten rytuał: otwierasz OLX, otwierasz Otomoto, przewijasz dziesiątki ogłoszeń, notujesz ceny w głowie, zamykasz kartę i następnego dnia zaczynasz od zera. Problem nie polega na braku danych — problem polega na tym, że tych danych jest za dużo, a żaden portal nie pokazuje Ci, jak cena konkretnego modelu zmieniała się w czasie, ile realnie trwa sprzedaż danego rocznika ani ile razy sprzedawca ruszał przy cenie po wystawieniu ogłoszenia.

Dokładnie z tej frustracji wyrósł Vehicleanalizer.com — mój projekt portfolio z 2020 roku, który zbudowałem jako rozszerzenie wcześniejszego CMS-a w .NET. Aplikacja cyklicznie pobiera ogłoszenia z portali ogłoszeniowych, wrzuca je do bazy danych i pokazuje je w formie sześciu różnych wykresów i statystyk. W tym wpisie rozbieram, jak to zostało poskładane, co wniosła warstwa analityczna i dlaczego historia ceny konkretnego ogłoszenia to w praktyce najciekawsza rzecz w całej aplikacji.

Aplikacja została stworzona po to, aby sprawdzać, jak często sprzedający dane modele samochodów na popularnych portalach. To jest dla mnie kluczowa informacja.

Jak aplikacja zbiera dane

Baza Vehicleanalizera to lista marek i modeli, które chcę obserwować. To nie jest scraper typu „zaciągnij wszystko, co się rusza” — to celowany tracker: definiuję, że chcę śledzić Chevroleta Camaro, Audi A6, Hondę Civic, i dopiero te modele są w obserwacji.

Sam proces pobierania stoi na kilku filarach:

  • Harmonogram — programy scrapujące odpalają się codziennie o określonej godzinie. To cyklicznie uruchamiane joby, które mielą każdy zdefiniowany model po kolei.
  • Scrapery na portale ogłoszeniowe — każde źródło (OLX, Otomoto) ma dedykowany moduł, który wie, jak wyglądają listingi i karty pojedynczego ogłoszenia. Dzięki temu zmiana layoutu na jednym portalu nie kładzie całego systemu.
  • Deduplikacja po identyfikatorze ogłoszenia — każdy rekord ma swoje źródło i unikalny klucz na portalu, więc przy kolejnym przebiegu aplikacja wie, że dane ogłoszenie już zna. Jeśli cena się zmieniła, dopisuje nowy wpis do historii.
  • Baza relacyjna — model pojazdu to jedna tabela, pojedyncze ogłoszenie to druga, a historia cenowa ogłoszenia to trzecia, spięta relacją jeden-do-wielu z ogłoszeniem.

Dzięki temu każdy pojazd w systemie ma swoją własną oś czasu: kiedy się pojawił, ile razy właściciel ruszał przy cenie, kiedy zniknął z portalu. To jest ta warstwa, której surowe ogłoszenia w ogóle nie mają — a która daje realną wartość przy wycenie rynkowej.

Wykresy i filtry — sześć ujęć tego samego auta

Wchodzisz w konkretny model, np. Chevrolet Camaro 3.6, i widzisz zestaw wykresów, które mają odpowiedzieć na kilka bardzo konkretnych pytań.

Na samej górze lądują statystyki ogólne: średnia cena wszystkich egzemplarzy pod daną flagą, zakres cenowy (np. 14 920 zł – 235 000 zł — tak, rozstrzał bywa absurdalny), zakres przebiegu, liczba wystawionych sztuk, zakres roczników.

Poniżej siedzi wykres cena/rocznik, który pokazuje, gdzie znajdują się najdroższe i najtańsze egzemplarze. Pozwala w sekundę wyłapać, że dany rocznik jest nieproporcjonalnie drogi albo odwrotnie — że obecnie na rynku jest dołek.

Potem wchodzi rozkład roczników do liczby sztuk — czyli których roczników jest na portalu najwięcej. To subtelna informacja, ale bardzo przydatna: jeśli danego rocznika jest 40 sztuk, a innego tylko 2, prawdopodobnie jeden z nich jest „hot” na rynku.

Kolejny wykres — i to jest moim zdaniem najciekawszy — to czas sprzedaży rocznika. Aplikacja liczy, ile średnio dni dany rocznik siedzi na portalu zanim zniknie. Jeśli 2011 sprzedaje się średnio 19 dni, a 2015 dwa dni, to wiesz dwie rzeczy: który rocznik trzyma cenę, a który rynek łyka od ręki.

Dalej są pojemność silnika vs cena i średni przebieg dla modelu, a na samym dole — lista wszystkich pojedynczych ogłoszeń, które aplikacja zapięła, wraz z czasem istnienia ogłoszenia na portalu. Klikam w konkretny rekord i wchodzę w historię ceny.

I tutaj dzieje się magia.

Historia ceny pojedynczego ogłoszenia

Każde ogłoszenie ma własny timeline z datami i kwotami. Jeśli właściciel nie ruszał przy cenie, historia jest płaska — jedna wartość. Jeśli kombinował, widzę dokładnie, kiedy i jak.

Konkretny przykład z aplikacji: auto zostało wystawione za 167 000 zł, po kilku dniach cena zjechała do 166 000 zł, a po tygodniu wróciła w górę. W interfejsie takie ogłoszenia mają czerwony pasek na dole — sygnalizator, że sprzedawca manipulował ceną.

To jest informacja, której nie zobaczysz nigdzie indziej. Portale ogłoszeniowe kasują starą cenę i pokazują nową jako „aktualną”. Vehicleanalizer trzyma wszystkie wartości i pozwala zobaczyć, czy sprzedawca faktycznie jest pod presją i obniża, czy tylko gra podbijanką, licząc na impulsywnego kupującego.

Widzimy dolny pasek na czerwono — to świadczy o tym, że sprzedawca kombinował przy cenie. Możemy sobie zobaczyć w historii pojazdu, że auto zostało wystawione za 167 tysięcy, następnie zmniejszone do 166, znowu podwyższone.

Z każdego rekordu prowadzi też bezpośredni link do oryginalnego ogłoszenia — żeby ocena nie była ślepa, tylko opierała się o konkretny egzemplarz, z VIN-em, opisem i zdjęciami.

Stos i architektura

Vehicleanalizer to aplikacja w ASP.NET Core — i to był świadomy wybór, bo cały szkielet stoi na moim wcześniejszym CMS-ie, który pokazywałem na kanale w osobnym filmie. CMS dał mi gotowy panel administracyjny, routing, autoryzację i warstwę bazy danych. Do tego dorobiłem moduł „pojazdy”, który jest sercem tej aplikacji.

Kluczowe elementy od strony technicznej:

  • Backend w .NET (ASP.NET Core) — kontrolery, serwisy, DI, EF Core jako warstwa dostępu do bazy.
  • Scheduler — cykliczne zadania uruchamiane w tle (wtedy zrobiłem to na własnym hostowanym schedulerze; dziś pewnie wziąłbym Hangfire albo Quartz.NET).
  • Scrapery — dedykowane klasy pod każde źródło, parsujące HTML ogłoszeń i mapujące je na wspólny model domenowy Vehicle + Listing + PriceHistoryEntry.
  • Baza relacyjna (MSSQL) — z indeksami pod najczęstsze zapytania (marka, model, rocznik, data pobrania).
  • Warstwa prezentacji — widoki Razor + biblioteka do wykresów po stronie klienta, która rysuje wszystkie sześć typów wizualizacji na podstawie JSON-a z backendu.
  • Deduplikacja i historia — prosty, ale kluczowy mechanizm: porównanie snapshotu dzisiejszego z wczorajszym i zapis różnic w tabeli historii.

Cały projekt jest dla mnie dobrym przykładem tego, że CMS jako baza pod kolejne aplikacje działa świetnie — zamiast pisać od zera kolejną aplikację z autoryzacją i panelem admina, dobudowałem moduł domenowy i skupiłem się na tym, co naprawdę wnosiło wartość: scrapery, harmonogram, analityka.

Vehicleanalizer był też pierwszym moim projektem, gdzie naprawdę zobaczyłem, jak zbieranie danych w czasie zmienia perspektywę. Jedno ogłoszenie to nic. Sto ogłoszeń dziennie przez trzy miesiące to już narzędzie, które widzi rynek inaczej niż człowiek przewijający listę.

Zobacz więcej

Tagi:#portfolio#dotnet#scraping#analytics#case-study

Masz pytanie do tego wpisu?

Napisz do mnie — chętnie porozmawiam o szczegółach technicznych, albo o tym jak zastosować to u Ciebie w projekcie.