Web scraping – techniki pisania web crawlerów w Pythonie
25-02-2024Web crawler, czy web scraper może okazać się wyjątkowo przydatnym skryptem nie tylko w Twojej pracy, ale także w codziennym życiu. Web scraping może pomóc Ci w tworzeniu zarówno odpowiednich statystyk, jak i automatycznego zbierania informacji. Web scraping w Pythonie jest wyjątkowo prosty, więc skorzystamy z tego języka programowania.
Spis treści
Web crawling i web scraping – porównanie
Niniejszy tekst jest dosyć ogólny i prezentuje raczej techniki i strategie pisania web crawlerów i web scraperów, aniżeli pokazuje konkretne implementacje. Z tego też powodu obu określeń używam zamiennie. Warto jednak wiedzieć jakie są różnice między nimi.
Web crawling | Zazwyczaj działa na wielu stronach internetowych – skacząc od jednej witryny do drugiej. Zazwyczaj zbiera dosyć ogólne dane, albo statystyki danych witryn. Może, np. nadawać im konkretne rangi, albo zajmować się ich indeksacją. Może też poszukiwać określonych informacji na wielu stronach. |
Web scraping | Zazwyczaj przeszukuje wyłącznie określone witryny. Zazwyczaj celem web scraperów jest znalezienie i przetworzenie ściśle określonych informacji. |
Web scraping po sitemapie
Sitemapy z założenia pomagają botom, przede wszystkim wyszukiwarkom na proste odnalezienie wszystkich adresów url na naszej stronie. Równie dobrze my możemy wykorzystać mapę strony do napisania własnego web crawlera. Web scraping przy użyciu tej metody na pewno będzie dosyć prosty do wdrożenia. Mamy w końcu pełną listę linków do odwiedzenia i nie musimy ich pobierać bezpośrednio z treści strony. Metoda ta będzie też dosyć szybka. Niestety ma bardzo dużo ograniczeń, przez co nie jest tak powszechnie używana, jak mogłoby się wydawać.
Po pierwsze – jesteśmy ograniczeni wyłącznie do stron znajdujących się w sitemapie. Pamiętaj, że część podstron mogło zostać wyindeksowanych i celowo nie znajdują się w mapie strony. Po drugie – nie znajdziesz tutaj adresów do zewnętrznych stron, a czasami chcemy po prostu przeskoczyć na kolejną stronę. W tym przypadku byłoby to możliwe, np. przy użyciu metody mieszanej, gdzie zbieramy adresy do postów za pomocą sitemapy i wchodzimy na nie, a później z treści pobieramy zewnętrzne odnośniki. Po trzecie – możemy nie mieć dostępu do sitemapy albo strona w ogóle może jej nie posiadać.
Przykładowa implementacja w języku Python
import requests
from bs4 import BeautifulSoup
def get_sitemap_urls(sitemap_url):
response = requests.get(sitemap_url)
soup = BeautifulSoup(response.text, 'html.parser')
# Znajdź wszystkie strony w sitemapie
urls = [loc.text for loc in soup.find_all('loc')]
return urls
def find_title_in_head(url):
try:
# Pobierz zawartość strony
response = requests.get(url)
# Utwórz obiekt BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Znajdź sekcję <head>
head_section = soup.head
# Znajdź element <title> w sekcji <head>
title_element = head_section.find('title')
# Zwróć zawartość elementu <title>
if title_element:
return title_element.text.strip()
else:
return "Nie znaleziono elementu <title> w sekcji <head>."
except requests.exceptions.RequestException as e:
return f"Błąd podczas pobierania strony: {e}"
def scrape_page(url):
title = find_title_in_head(url)
print(f"Scraping: {url}")
print(f"Title: {title}")
if __name__ == "__main__":
sitemap_url = "https://example.com/sitemap.xml" # wstaw adres url do scrapowania
urls = get_sitemap_urls(sitemap_url)
for url in urls:
scrape_page(url)
Web crawling po konkretnych stronach
Bardzo często pisząc web crawler, Twoim celem będzie zbieranie danych ze ściśle określonych stron. Bardzo ułatwia nam to sprawę, ponieważ jesteśmy w stanie precyzyjnie określić w którym miejscu znajdują się interesujące nas informacje. Nie musimy brać pod uwagę tak wielu wariantów. W moim wpisie o podstawach pisania web crawlerów pokazałem jak można napisać taki skrypt.
Oczywiście metod na scrapowanie tych danych jest wiele. Wyobraźmy sobie, że strona posiada paginację w formacie ?page=1. Zastanówmy się jak możemy napisać web crawler
- Możemy od razu pobrać adresy adresy paginacji bezpośrednio ze strony
- Możemy sprawdzić ile jest stron paginacji, a następnie stworzyć pętlę, w której będziemy tylko podstawiać numer strony
- Możemy w ogóle nie wiedzieć ile mamy stron, ale możemy napisać pętlę, która zostanie zakończona w momencie, kiedy podstawiona w adresie url strona nie zwróci już wyników.
Ale po co w zasadzie zbierać informacje z konkretnych stron? Wyobraźmy sobie, że szukamy pracy jako programista PHP. W Internecie mamy wiele stron z ogłoszeniami. Możemy więc napisać skrypt, który w przeciągu kilku sekund pobierze dane z popularnych portali, a następnie odfiltruje te, które nas nie interesują. Całkiem przydatne, nieprawdaż?
Albo z drugiej strony – chcemy tworzyć statystyki na temat runku używanych instrumentów muzycznych. Możemy napisać web crawler, który będzie skakał po portalach z ogłoszeniami i pobierał interesujące nas dane, a następnie przygotuje dla nas raport, albo zapisze dane chociażby w bazie danych.
Siłowy web scraping
Jedną z technik na scrapowanie strony jest pobranie wszystkich linków na stronie, a następnie przechodzenie pomiędzy nimi. Należy jednak zauważyć, że w tym przypadku musisz wdrożyć kolejnych mechanizm, dzięki któremu Twój web crawler nie będzie wchodził kilka razy na tę samą stronę. Możesz więc zapamiętać, albo zapisać wszystkie adresy url pobrane z pierwszej strony, a następnie przechodząc na kolejne podstrony będziesz znowu pobiera linki, sprawdzając jednocześnie, czy nie były już odwiedzone.
Taktyczny web crawling
Innym podejściem, jest taktyczne podejście do pisania web crawlera. Temat jest bardzo szeroki, i poruszę go wyłącznie na najbardziej podstawowym poziomie. Weź pod uwagę, że większość stron będzie działała na podobnych zasadach, więc nasze skrypty mogą wykorzystywać pewne założenia do zrozumienia strony. Przykładowo – główna nawigacja zazwyczaj będzie znajdować się w znacznikach <nav>, dzięki czemu możemy starać się wyszukać ten element i pobrać, np. linki do naszych kategorii. Z dużym prawdopodobieństwem, mapa strony znajduje się pod adresem /sitemap.xml, albo po wejściu na ten adres zostaniemy przeniesieniu do sitemapy. Mając wystarczająco dużo założeń na temat funkcjonowania stron, możemy napisać web crawler, który da radę zbierać informacje z większości stron WWW.
Web crawler po wielu stronach
Bardzo często naszym celem nie jest konkretna domena, ale chcemy zbierać określone dane z wielu stron. Pisanie takich web crawlerów jest znacznie bardziej skomplikowane, niż pisanie prostego skryptu do scrapowania określonej strony. Pamiętajmy, że drzewo DOM każdej strony może być nieco inne, a strategii na web crawling wielu różnych stron – całe mnóstwo, ale zazwyczaj są to metody mieszane.
Pomysł pierwszy – scrapujemy stronę po sitemapie, dzięki czemu uzyskujemy w prosty sposób adresy wszystkich postów. Następnie wewnątrz postów szukamy zewnętrznych linków. Metoda fajnie sprawdzi się przy stronach na WordPress, ponieważ pluginy takie jak Yoast, czy Rank Math, automatycznie generują mapę strony i posiada ona oddzielną mapę postów, co ułatwia sprawę.
Pomysł drugi – Skaczemy po stronach w sposób klasyczny, wyciągamy wszystkie linki z sekcji body, a następnie filtrujemy wyniki tak, żeby zostały nam wyłącznie linki zewnętrzne. Możemy też na tym etapie odrzucić te, których nie chcemy, np. linku do strony WordPressa, który bardzo często się pojawia. Pamiętaj jednak, że w takim przypadku musisz zaprojektować crawler, który nie tylko pobierze informacje o wszystkich stronach, ale także zrobić to w sposób najbardziej efektywny.
Oczywiście technik i strategii na napisanie web crawlera jest dużo więcej, a wszystko zależy od tego, czego tak na prawdę potrzebujesz.
Podsumowanie
Podsumowując – nniejszy tekst porusza temat różnic pomiędzy web scrapingiem i web crawlingiem, a także różnych technik pobierania interesujących danych ze stron internetowych. Pokazałem też przykładową implementację w języku Python.