Scrapy trafia do szufladki „nie radzi sobie ze współczesnymi stronami”, bo nie uruchamia JavaScriptu. To ocena postawiona na głowie. Brak renderowania strony jest tu właśnie sednem, a kiedy zobaczysz ten mechanizm w praktyce, przestaje to wyglądać jak brakująca funkcja.
Przekonałem się o tym w jednym przebiegu. Zbudowałem testowy katalog renderowany przez JavaScript, wskazałem Scrapy stronę, którą pokazałaby przeglądarka, i dostałem z powrotem 0 kart produktów. Potem skierowałem tego samego pająka do punktu końcowego JSON, który ta strona po cichu odpalała w tle, i otrzymałem 8/8 elementów — czysto i bez śmieci. To samo narzędzie, ta sama sesja, dwa zupełnie różne wyniki. I właśnie ta różnica jest osią tej recenzji.
Czym Scrapy naprawdę jest, a czym nie jest

Scrapy to framework w Pythonie do crawlowania stron i wyciągania danych w ustrukturyzowanej formie. Tak opisują go sami twórcy w dokumentacji ogólnej, i po korzystaniu z niego trzeba przyznać, że to trafny opis — bez marketingowego nadęcia. Jest wystarczająco dojrzały i rozpowszechniony, by być pierwszą odpowiedzią, gdy programista Pythona pyta, czego używają poważni ludzie do scrapowania. Potwierdza to też repozytorium: około 62 981 gwiazdek na GitHubie według stanu na 2026-07-07 (scrapy/scrapy), 11 773 forki i 590 otwartych zgłoszeń tego samego dnia. Licencja BSD-3-Clause, Python 3.10 lub nowszy, a wersja, którą sprawdziłem, to 2.17.0 — akurat wydana rano, kiedy odpalałem testy, więc bez żadnych „ale to była starsza wersja”.
Oto granica, która odróżnia Scrapy od nowszych narzędzi z obszaru AI crawlingu: domyślnie działa tylko po HTTP. Bez przeglądarki. Bez silnika renderującego. Pobiera HTML przez sieć, przekazuje go parserowi i pozwala wyciągać pola za pomocą selektorów CSS albo XPath. Nazwanie tego ograniczeniem jest tylko częściowo prawdziwe i mija się z założeniem projektu. Scrapy wychodzi z prostego założenia: uruchamianie headless Chrome przy zwykłym scrapowaniu to zazwyczaj zły wybór — rozsądniej jest znaleźć żądanie danych, które i tak wykonuje strona, i odwołać się bezpośrednio do niego.
To nie jest moja interpretacja dopisana do narzędzia. Oficjalna dokumentacja o dynamicznej treści mówi to wprost: najpierw znajdź i odtwórz źródłowe żądanie danych, a po przeglądarkę bez interfejsu sięgaj dopiero wtedy, gdy nie da się tego praktycznie odtworzyć. Większość scraperów otwiera przeglądarkę jako pierwszy krok i w ogóle nie myśli o API. Scrapy odwraca ten domyślny wzorzec.
Najważniejsze funkcje i logika stojąca za każdą z nich
Pod maską Scrapy to zestaw elementów, z których każdy zakłada jedno: że jesteś programistą, który chce kontroli, a nie kreatora „kliknij i gotowe”.
Spidery. Tworzysz klasę, podajesz adresy startowe i definiujesz callback parse, który zwraca elementy albo przechodzi do kolejnych linków. To więcej pisania niż w przypadku no-code extractorów — reguły ekstrakcji tworzysz sam — ale w zamian dostajesz precyzyjną kontrolę nad tym, co zostanie zebrane i dokąd crawler pójdzie dalej.
Selektory. Parsowanie opiera się na parsel, a pod spodem działa lxml. CSS i XPath są tu rozwiązaniami pierwszej klasy, a nie dodatkiem przyklejonym na siłę. To właśnie zasługa lxml, że selekcja pozostaje szybka, a kod ekstrakcji czyta się jak jasno sformułowany zamiar, a nie plątaninę cięć stringów.
Eksport feedów. Skieruj pająka do pliku, a Scrapy zapisze elementy do JSON, JSON Lines, CSV albo XML bez dodatkowego klejenia kodu. W moim teście jeden spider dla statycznego katalogu zapisał zarówno JSON, jak i CSV bez ani jednej linijki kodu eksportu z mojej strony — feed export działa naprawdę i robi to, co obiecuje.
AutoThrottle i kontrola crawlowania. Żądania są planowane asynchronicznie na Twisted, a do dyspozycji masz limity współbieżności, opóźnienia pobierania, ograniczenia głębokości, AutoThrottle do adaptacyjnego limitowania tempa oraz posłuszeństwo wobec robots.txt. To właśnie te mechanizmy zapobiegają temu, by szeroki crawl zamienił się w akcję obciążania serwera.
Tylko HTTP — ale jako zaleta. Brak przeglądarki oznacza małe zużycie pamięci, wysoką przepustowość i brak silnika renderującego, którym trzeba się zajmować — o ile dane, których szukasz, są dostępne przez zwykłe HTTP. A często są, częściej niż zakładają zwolennicy podejścia „najpierw przeglądarka”.
Instalacja: stos zależności, którego nikt nie wrzuca na zrzuty ekranu

Instalacja była bezproblemowa, a przy frameworku tej skali warto to powiedzieć wprost. pip install Scrapy==2.17.0 zakończył się czysto w świeżym virtualenv na macOS arm64, pobierając binarne wheel’e, bez żadnego kompilowania się w ścianę. Nie było dramatu — i o to chodzi.
Ale spójrzmy, co faktycznie zostało doinstalowane. scrapy version -v pokazało Scrapy 2.17.0 działające na lxml 6.1.1, Twisted 26.4.0, pyOpenSSL 26.3.0 i cryptography 49.0.0, z parsel, cssselect i tldextract dopełniającymi cały zestaw. To już poważny ślad w systemie — pełny crawlerowy stack, a nie jednoplikowy parser HTML. Na tej maszynie do wszystkiego były wheel’e i instalacja przebiegła bezboleśnie. Na innych konfiguracjach oficjalna dokumentacja wciąż ostrzega przed problemami zależnymi od platformy, a historycznie najbardziej kłopotliwe bywają elementy związane z cryptography i Twisted, więc warto to uwzględnić, jeśli pracujesz na czymś nietypowym. U mnie instalacja poszła gładko, ale sam rozmiar pakietu nadal jest istotną informacją, zanim się zdecydujesz — instalujesz framework i dostajesz ciężar frameworka.
Test praktyczny: co zadziałało

Po instalacji ścieżka statyczna działała bez zarzutu. Pełny recall, nic nie wypadło.
| Test | Wynik | Czas działania |
|---|---|---|
| Lokalny statyczny katalog + paginacja | 12/12 produktów | 0.557s |
| Eksport CSV dla statycznego katalogu | zapisano 12 wierszy | (ta sama sesja) |
| Ekstrakcja artykułu | tytuł + 3/3 akapity treści | 0.416s |
| Graph crawl, DEPTH_LIMIT=2 | 11 stron na głębokościach 0/1/2 | 0.904s |
| Lokalna strona 500 | status 500 przechwycony, brak awarii | 0.424s |
| Books to Scrape (publiczne) | 20 produktów | 2.053s |
| Quotes to Scrape spider (publiczne) | 12 cytatów | 3.465s |
Spider dla statycznego katalogu przeszedł przez paginację ze strony pierwszej do drugiej i zebrał 12/12 oczekiwanych rekordów, po czym zapisał je jako JSON i CSV w tym samym przebiegu. Najciekawszy był fixture z artykułem. Scrapy nie próbowało automatycznie „wygładzić” strony do eleganckiego Markdowna — zamiast tego pozwoliło mi wskazać pola article za pomocą jawnych selektorów i odseparowało treści z nawigacji oraz stopki do osobnych pól. Dzięki temu dostałem 3/3 akapity treści, a cały boilerplate pozostał odizolowany, zamiast rozlać się po wyniku. I właśnie to jest kompromis: sam definiujesz selektory, a w zamian dostajesz dokładnie to, o co poprosiłeś, i nic więcej.
Kontrola crawlowania sprawdziła się na małą skalę. Przy DEPTH_LIMIT=2, krótkim opóźnieniu pobierania, współbieżności ustawionej per domena i włączonym robots.txt crawl graph objął 11 stron na głębokościach 0, 1 i 2, a zliczanie głębokości działało prawidłowo. Obsługa błędów była równie spokojna. Celowo przygotowana strona 500 wróciła jako uporządkowany element ze statusem 500 przekazanym przez handle_httpstatus_list — bez wyjątku, bez wywracania całego runu. Scrapy traktuje status błędu jako coś, czym zajmujesz się w logice spidera, a nie jako niespodziankę, która wysadza crawl.
Test praktyczny: ściana JavaScriptu i drzwi obok niej

A teraz wynik, wokół którego zbudowana jest ta recenzja.
Skierowałem HTTP fetcher Scrapy na katalog renderowany przez JavaScript. Pobrał HTML źródłowy, znalazł 0 węzłów .product-card i poszedł dalej — bo nigdy nie uruchomił skryptu, który narysowałby te karty. Publiczna strona Quotes to Scrape JS page pokazała dokładnie to samo: 0 wyrenderowanych węzłów cytatów. Na tym etapie łatwo byłoby uznać, że Scrapy nie nadaje się do niczego, co powstało po tej dekadzie.
Ale nie warto kończyć właśnie tutaj. Ten katalog JS był zasilany w tle przez API JSON, jak większość podobnych przypadków. Skierowałem tego samego spidera Scrapy do tego endpointu i dostałem 8/8 produktów w 0.416s — bez przeglądarki, bez renderowania, po prostu zapytanie do URL, który strona i tak już wywoływała, i parsowanie odpowiedzi JSON.
To zestawienie obok siebie świetnie pokazuje filozofię „odtwórz żądanie”. Renderowana strona jest przynętą; dane cały czas siedziały za API, a projekt Scrapy prowadzi cię do bezpośredniego uderzenia w to źródło zamiast płacenia za headless browser, który tylko patrzy, jak strona składa się do kupy. Jest szybciej, lżej i mniej awaryjnie — kontrakt API zwykle jest stabilniejszy niż cała masa DOM-u po stronie klienta. Jest tylko jeden haczyk: wszystko trzeba zrobić ręcznie. Musisz otworzyć zakładkę sieci, znaleźć żądanie i samodzielnie odtworzyć nagłówki oraz parametry. Scrapy nie odkryje API za ciebie — po prostu sprawia, że po jego znalezieniu użycie jest banalne.
Dwie granice, jasno nazwane. Jeśli naprawdę nie ma żadnego źródłowego żądania do odtworzenia — bo dane są wbudowane wyłącznie przez renderowanie po stronie klienta i nie stoją za nimi żadne API — Scrapy potrzebuje integracji z headless browserem, którą musisz podłączyć samodzielnie, a w tej rundzie nie testowałem takiej ścieżki. Poza tym wszystkie wyniki dotyczą małych fixture’ów i publicznych stron demo. Nie uruchamiałem crawlów na 100–1000 stron, więc nie roszczę sobie prawa do wniosków o pamięci, przepustowości czy zachowaniu retry na dużej skali — asynchroniczny rdzeń i kontrola crawlowania są obiecujące, ale sygnał to jeszcze nie pomiar.
Zalety i wady
Zalety:
- Architektura tylko HTTP jest szybka i lekka — 12/12 statycznych rekordów w około pół sekundy, 8/8 z API JSON w 0.416s, bez narzutu przeglądarki.
- Podejście „odtwórz żądanie” naprawdę działa: strona JS, która dawała 0, oddała wszystkie 8 elementów przez swoje API.
- Selektory CSS i XPath oparte na
lxmlsprawiają, że kod ekstrakcji jest czytelny i szybki. - Eksport do JSON/CSV/XML działa od ręki, bez dodatkowego kodu eksportowego.
- Jawna obsługa błędów — 500 wraca jako status do przechwycenia, a nie crash.
- Dojrzałe mechanizmy crawlowania: współbieżność, opóźnienia, limity głębokości, AutoThrottle, robots.txt.
- Przyjazna licencja BSD-3-Clause; czysta instalacja na nowoczesnym systemie.
Wady:
- Z założenia nie renderuje JavaScriptu — na stronie renderowanej po stronie klienta zobaczysz 0 węzłów, dopóki sam nie znajdziesz API.
- Odszukanie właściwego żądania jest ręczne; Scrapy nie wskaże ci endpointu.
- Spory stos zależności (Twisted, lxml, cryptography, pyOpenSSL, parsel, tldextract) — u mnie bezproblemowy, ale na nietypowych platformach historycznie bywał źródłem tarć.
- Więcej kodu niż w narzędziach no-code lub automatycznych ekstraktorach; spidera musisz pisać i utrzymywać samodzielnie.
- Testy objęły małe fixture’y i demo stron, a nie duże crawle — niezawodność na skali nie została tu udowodniona.
Dla kogo to narzędzie, a kto powinien je ominąć

Scrapy jest dla programistów, którzy chcą kontroli na poziomie kodu i myślą w kategoriach requestów, a nie stron. Jeśli na powolną stronę z JavaScriptem twoją pierwszą myślą jest „na pewno siedzi tu jakieś API”, to właśnie pod taki odruch to narzędzie zostało zbudowane. Nagradza osoby, które potrafią pisać selektory, czytać zakładkę sieci i brać odpowiedzialność za logikę ekstrakcji od początku do końca. Dla statycznych stron, katalogów z paginacją i wszystkiego, co ma wykrywalny endpoint JSON, jest szybkie i precyzyjne.
Omiń je — albo przynajmniej połącz z czymś innym — jeśli pisanie i utrzymywanie kodu spiderów nie jest tym, na co chcesz poświęcać czas, albo jeśli twoje źródła renderują dane wyłącznie po stronie klienta bez dającego się odtworzyć requestu i nie chcesz samemu doklejać headless browsera. A jeśli marzyło ci się narzędzie, do którego wklejasz URL i dostajesz czysty, ustrukturyzowany wynik bez pisania reguł ekstrakcji, to nigdy nie było zadaniem Scrapy — i nigdy nie udawało, że nim jest.
Alternatywy i miejsce Thunderbit
Wypróbuj Thunderbit do ekstrakcji danych z sieci
Zacznij od tego, na co się decydujesz: darmowy, open-source’owy framework, który uruchamiasz i utrzymujesz samodzielnie. To ty odpowiadasz za spidery, stos zależności i znalezienie żądania danych dla każdej strony. W zamian nie płacisz za request, wszystko zostaje u ciebie, a kontrola jest absolutna. Dla wielu zespołów to właściwy wybór i ta recenzja nie ma nikogo od niego odwodzić.
Koszt pojawia się przy problemie renderowania i zmian w strukturze stron, a odpowiedź Scrapy brzmi: to ty to rozwiązujesz — znajdujesz API, odtwarzasz request i w przypadku braku API sam dokładasz przeglądarkę. Zarządzane API do scrapingu AI zdejmuje tę warstwę z twoich barków. Właśnie w tym miejscu znajduje się dla bardziej technicznych czytelników Thunderbit — jako stack developerów: AI scraping API + serwer MCP + CLI, a nie rozszerzenie przeglądarki używane przez dział sprzedaży i operacji. POST /distill zamienia stronę w czysty, gotowy dla LLM Markdown; POST /extract zwraca ustrukturyzowany JSON według schematu, który definiujesz; oba warianty obsługują renderowanie JavaScriptu, anti-bot i dynamiczną treść po stronie serwera — także przypadek renderowania po stronie klienta, w którym Scrapy każe ci sięgnąć po przeglądarkę. Jest też serwer MCP dla agentów AI i asystentów programistycznych (z darmowym thunderbit_suggest_fields do rozpoznania zakresu strony, zanim cokolwiek wydasz) oraz CLI uruchamiane przez npx @thunderbit/thunderbit-cli do pracy w terminalu, CI albo cronie.
Różnica nie dotyczy jakości, tylko własności procesu. Scrapy to jawny framework inżynierski: utrzymujesz spidera, pipeline i strategię dla JS, a w zamian dostajesz pełną kontrolę bez kosztu per call. Stack Thunderbit oddaje warstwę renderowania i ekstrakcji jako usługę zarządzaną, więc omijasz grzebanie w zakładce sieci i płacisz za wywołania. Mała skala, podejście code-first i chęć kontrolowania każdego kroku? Scrapy będzie lepszym dopasowaniem. Skalowanie na sto witryn i brak ochoty na ręczne odtwarzanie requestu dla każdej z nich? Zarządzana ścieżka usuwa całą tę klasę pracy.
Dla szerszego kontekstu te benchmarkowe teksty opisują sąsiadów z tego samego obszaru: pełne porównanie open-source’owych scraperów, recenzję crawlера Go bez przeglądarki — Colly oraz recenzję adaptacyjnych selektorów Scrapling.
Werdykt
Czy warto używać Scrapy? Tak — jeśli jesteś programistą, który chce kontroli, i kupujesz tę filozofię: nie renderuj strony, tylko znajdź stojące za nią żądanie. W testach ta logika zadziałała dokładnie tak, jak obiecuje. Katalog JS zwrócił HTTP fetcherowi 0 kart, a zasilające go API JSON oddało temu samemu spiderowi wszystkie 8 elementów. Ekstrakcja statyczna trafiła w 12/12, selektory artykułów utrzymały 3/3 akapity poza boilerplate’em, graph crawl respektował limit głębokości na 11 stronach, a 500 wróciło jako obsłużony status zamiast awarii.
Trzeba jednak dobrze rozumieć zakres tych wniosków. Scrapy nie renderuje JavaScriptu i nie odkryje API za ciebie — ten odruch musisz wypracować sam. Stos zależności jest pełny jak na framework i na nietypowych platformach może sprawiać problemy, mimo że u mnie wszystko przebiegło czysto. A ponieważ testowałem fixture’y i strony demo, a nie crawl na tysiąc stron, traktuj historię o skali jako obiecującą, ale nieudowodnioną. W tych granicach Scrapy jest narzędziem, które najodważniej trzyma się cichej, ale radykalnej idei: najszybsza droga przez stronę WWW zwykle nie prowadzi przez samą stronę.
Wypróbuj Thunderbit do ekstrakcji danych z sieci Get Started Free
FAQ
Czy Scrapy potrafi pobierać strony renderowane przez JavaScript? Nie przy użyciu domyślnego fetchera HTTP — na testowym JS fixture i publicznej stronie Quotes JS zwrócił 0 węzłów, bo pobiera HTML bez uruchamiania przeglądarki. Docelowa ścieżka polega na znalezieniu źródłowego żądania danych i bezpośrednim odwołaniu się do niego; w moim teście API JSON stojące za katalogiem JS oddało wszystkie 8 elementów. Jeśli strona nie ma dającego się odtworzyć requestu, musisz sam podpiąć headless browser.
Co właściwie znaczy „odtworzyć żądanie”? Większość dynamicznych stron ładuje dane z API JSON w tle, a potem renderuje je po stronie klienta. Zamiast uruchamiać przeglądarkę i obserwować ten proces, otwierasz zakładkę sieci, odnajdujesz to wywołanie API i wskazujesz Scrapy bezpośrednio ten adres. To szybsze i stabilniejsze niż renderowanie — kontrakt API psuje się rzadziej niż DOM — ale wymaga ręcznej pracy, a Scrapy nie wyszuka endpointu za ciebie.
Czy instalacja Scrapy jest trudna?
U mnie była bezproblemowa — pip install Scrapy==2.17.0 zakończył się bez błędów kompilacji w świeżym venv na macOS z binarnymi wheel’ami. Ale narzędzie pobiera spory stos zależności (Twisted, lxml, cryptography, pyOpenSSL, parsel, tldextract), a oficjalna dokumentacja nadal ostrzega przed tarciami zależnymi od platformy na niektórych systemach, więc warto to uwzględnić, jeśli pracujesz na czymś niestandardowym.
Jakie formaty wyjściowe obsługuje Scrapy? Eksport feedów działa od razu i obejmuje JSON, JSON Lines, CSV oraz XML — wystarczy wskazać spiderowi plik, a elementy zostaną zapisane bez dodatkowego kodu. W moim teście jeden spider wygenerował jednocześnie JSON i CSV w jednym przebiegu. Pamiętaj tylko, że eksportuje pola, które sam wybrałeś; nie czyści automatycznie strony do formatu Markdown.
Czy Scrapy można używać komercyjnie za darmo? Tak, bo ma licencję BSD-3-Clause, czyli przyjazną i elastyczną także dla zastosowań komercyjnych. Jak zawsze, przed wdrożeniem sprawdź aktualną licencję w repozytorium i odpowiedzialnie ustawiaj user-agent, proxy oraz limity tempa — możliwość nie oznacza jeszcze przyzwolenia.


