Moduł 1 · Podstawy web scrapingu i środowisko pracy
Jak działa strona: HTTP, HTML i drzewo DOM
Po tej lekcji wyjaśnisz, co dzieje się między Twoim skryptem a serwerem, gdy pobierasz stronę, i odczytasz z kodu HTML miejsce, w którym leżą potrzebne dane. Aktualne na: październik 2026.
Przez cały kurs pracujesz na fikcyjnym sklepie internetowym Palarnia Ziarenko z Krakowa. Jego kopię uruchomisz na własnym komputerze (pliki z modułu 1), więc możesz ćwiczyć bez obciążania cudzych serwerów. Ceny są w złotych, a strona ma celowo wbudowane pułapki, które spotkasz w prawdziwych serwisach: brak ceny, twardą spację w „1 249,00 zł”, link bezwzględny zamiast względnego i treść ładowaną skryptem.
Żądanie i odpowiedź HTTP
Web scraping to automatyczne pobieranie stron i wyciąganie z nich danych. Każde pobranie strony to rozmowa według protokołu HTTP: Twój program wysyła żądanie, serwer odsyła odpowiedź. Żądanie składa się z metody (najczęściej GET, czyli „daj mi zasób”), adresu, nagłówków i czasem treści. Odpowiedź ma kod statusu, nagłówki i treść, na przykład dokument HTML albo JSON.
GET /kawa/strona-1.html HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: ZiarenkoKursBot/1.0 (kontakt: twoj-adres@example.com)
Accept: text/html
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.12.3
Content-type: text/html
Content-Length: 3661Powyżej masz prawdziwą odpowiedź serwera ćwiczeń (moduł http.server z biblioteki standardowej Pythona), skróconą o datę.
Nagłówki niosą informacje, które szybko okażą się ważne. User-Agent mówi serwerowi, kto pyta. Dobra praktyka to przedstawić się nazwą bota i kontaktem do siebie, a nie udawać przeglądarki. Content-Type mówi, w jakim formacie i kodowaniu jest odpowiedź. Serwer ćwiczeń podaje samo text/html bez informacji o kodowaniu i w lekcji 1.4 zobaczysz, jak to psuje polskie znaki.
Kody statusu, które scraper musi rozumieć, zgodnie z RFC 9110 (semantyka HTTP) i RFC 6585 (kod 429):
Źródło: RFC 9110 i RFC 6585. Szczegóły reakcji w module 6.
Zwróć uwagę na 403 i 429. To nie są przeszkody do „obejścia”, tylko sygnały od właściciela serwera. W module 6 nauczysz się na nie odpowiadać tak, żeby Twój scraper był przewidywalny i nie szkodził serwisowi.
HTML: gdzie leżą dane
Przeglądarka zamienia HTML w wygląd strony. Scraper czyta ten sam HTML, ale interesuje go struktura. Oto karta jednego produktu ze sklepu ćwiczeń:
<article class="produkt" data-sku="ZK-001" data-kategoria="kawa">
<h2 class="nazwa"><a href="/produkt/zk-001.html">Brazylia Santos 250 g</a></h2>
<p class="cena"><span class="cena-stara">49,00 zł</span> <span class="cena-aktualna">42,90 zł</span></p>
<p class="dostepnosc" data-stan="12">Dostępny</p>
<div class="ocena" data-ocena="4.6">Ocena 4,6 (23 opinii)</div>
</article>Znacznik (tag) to nazwa w nawiasach ostrych, na przykład article, h2, span. Atrybuty dopisują informacje: class grupuje elementy o podobnej roli, id powinien być jeden na stronie, href to adres linku, a atrybuty data-* to własne dane twórców strony. Atrybuty data-* są często najlepszym źródłem: data-stan="12" daje liczbę sztuk bez parsowania słowa „Dostępny”, a data-ocena="4.6" liczbę z kropką zamiast tekstu „Ocena 4,6”.
Dobra zasada: zanim napiszesz selektor, otwórz stronę w przeglądarce, kliknij prawym przyciskiem na cenę i wybierz „Zbadaj” (narzędzia deweloperskie). Zobaczysz element w drzewie i jego klasy. Szukaj klas, które opisują znaczenie (cena-aktualna), a nie wygląd (text-red-500), bo te drugie zmieniają się przy każdym odświeżeniu szablonu.
Drzewo DOM i selektory CSS
Przeglądarka i biblioteki do parsowania budują z HTML drzewo DOM (Document Object Model). Każdy element ma rodzica, dzieci i rodzeństwo: article jest rodzicem h2, a h2 i p.cena są rodzeństwem. Po tym drzewie poruszasz się w kodzie, a elementy wskazujesz selektorami CSS, tymi samymi, których używają projektanci stron.
Selektory sprawdzone na stronie ćwiczeń Palarni Ziarenko.
Najczęstsze formy selektorów: div.produkt (znacznik z klasą), #koszyk (identyfikator), article > h2 (bezpośrednie dziecko), article h2 (potomek na dowolnym poziomie), a[href] (element z atrybutem), p[data-stan="0"] (atrybut o konkretnej wartości). Pseudoklasa :has() wybiera rodzica, który zawiera dany element. BeautifulSoup obsługuje ją przez bibliotekę Soup Sieve, więc w module 2 jednym selektorem wybierzesz wszystkie produkty w promocji.
Na koniec ważna obserwacja: nie każda strona ma dane w HTML wysłanym przez serwer. Strona „Nowości” sklepu ćwiczeń przychodzi z pustą listą, a produkty dorysowuje skrypt JavaScript, który pobiera plik JSON. Zwykłe pobranie przez Pythona zobaczy tylko napis „Ładowanie…”. Takimi stronami zajmiesz się w module 3, a w lekcji 3.4 nauczysz się sięgać od razu po ten JSON.
Najważniejsze w 3 punktach
- Każde pobranie strony to żądanie i odpowiedź HTTP; kod statusu mówi, co zrobić dalej, a 403 i 429 to sygnały do zatrzymania lub zwolnienia.
- Dane leżą w drzewie DOM: wskazujesz je selektorami CSS, najlepiej po klasach opisujących znaczenie i po atrybutach
data-*. - Część stron dorysowuje treść skryptem, więc zanim napiszesz parser, sprawdź, czy dane są w HTML wysłanym przez serwer.
Źródła
- RFC 9110, HTTP Semantics (2022), kody statusu i nagłówki: https://www.rfc-editor.org/rfc/rfc9110
- RFC 6585, Additional HTTP Status Codes, kod 429: https://www.rfc-editor.org/rfc/rfc6585
- MDN Web Docs, selektory CSS i
:has(): https://developer.mozilla.org/pl/docs/Web/CSS/CSS_selectors - Dokumentacja Beautiful Soup 4.15, selektory CSS przez Soup Sieve: https://www.crummy.com/software/BeautifulSoup/bs4/doc/
- Strona ćwiczeń Palarnia Ziarenko: plik M1_start_i_robots.zip w materiałach kursu (sklep fikcyjny).