1. Podstawy pracy ze skomplikowanymi strukturami HTML
Zanim zaczniemy analizować skomplikowane struktury HTML, warto zrozumieć, dlaczego HTML może być tak zagmatwany. Deweloperzy stron często używają złożonych zagnieżdżonych elementów do organizacji treści, co może przerodzić się w prawdziwy koszmar dla tych, którzy próbują wyodrębnić dane z takich stron. Ale spokojnie — kiedy masz dobry plan i narzędzia, poradzisz sobie bez problemu!
Analiza drzewa HTML
Wyobraź sobie dokument HTML jako drzewo: każdy element —
to węzeł, który może zawierać tekst lub inne węzły. Na
szczycie tego drzewa stoi html
, za nim podążają
head
i body
, a dalej rozmieszczone są
różne elementy potomne. Zagnieżdżone elementy znajdują się
głębiej w tym drzewie.
Przykład prostej struktury HTML:
<html>
<head>
<title>Przykład</title>
</head>
<body>
<div class="content">
<h1>Nagłówek</h1>
<p>Akapit 1</p>
<p>Akapit 2</p>
<div class="nested">
<ul>
<li>Element 1</li>
<li>Element 2</li>
<li><span>Element 3</span></li>
</ul>
</div>
</div>
</body>
</html>
Jak widzisz, mamy div
z klasą
nested
, który zawiera ul
, a
ten z kolei jest wypełniony li
. To przykład
tego, jak elementy mogą być zagnieżdżone.
2. BeautifulSoup
do wyodrębniania danych
Wyodrębnianie danych z zagnieżdżonych elementów
Przypomnijmy sobie, jak działa BeautifulSoup. Użyjmy go,
aby wyodrębnić tekst z listy
li
. Czas wcielić się w prawdziwego detektywa i zebrać
dane z naszych zagnieżdżonych struktur.
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
nested_items = soup.select('.nested ul li')
for item in nested_items:
print(item.get_text())
Wynik:
Element 1
Element 2
Element 3
Jak widzisz, użyliśmy metody select
z
selektorem CSS, aby znaleźć wszystkie li
wewnątrz
elementu z klasą nested
. Metoda
get_text()
umożliwia wyodrębnianie tekstu
bezpośrednio z znalezionych elementów.
3. Praca z wielopoziomowymi elementami
Czasami dane znajdują się nie tylko w głębi struktury, ale też rozproszone na różnych poziomach, co czyni zadanie wyodrębniania bardziej skomplikowanym. Zobaczmy, jak wyodrębniać dane z bardziej skomplikowanego drzewa HTML.
Przykład skomplikowanej struktury:
<html>
<body>
<div class="wrapper">
<div class="header">
<h1>To jest nagłówek</h1>
</div>
<div class="content">
<div class="article">
<h2>Artykuł 1</h2>
<p>Treść artykułu 1</p>
</div>
<div class="article">
<h2>Artykuł 2</h2>
<p>Treść artykułu 2</p>
</div>
</div>
<div class="footer">
<p>Informacje kontaktowe</p>
</div>
</div>
</body>
</html>
Wyodrębnianie danych z poziomów
Teraz spróbujmy wyodrębnić tytuły wszystkich artykułów oraz ich treści.
articles = soup.select('.content .article')
for article in articles:
title = article.find('h2').get_text()
content = article.find('p').get_text()
print(f'Tytuł: {title}')
print(f'Treść: {content}\n')
Oczekiwany wynik:
Tytuł: Artykuł 1
Treść: Treść artykułu 1
Tytuł: Artykuł 2
Treść: Treść artykułu 2
Używamy połączenia metod select
i
find
, aby osiągnąć nasze cele.
select
pomaga znaleźć element nadrzędny, a
find
wyodrębnia informacje z potomnych.
4. Cechy pracy z zagnieżdżonymi elementami
Przeszukując strony internetowe, możesz natknąć się na problemy, takie jak obecność wielu zagnieżdżonych elementów z identycznymi klasami lub tagami. W takich przypadkach użycie kontekstowego wyszukiwania i dokładna identyfikacja potrzebnych elementów pomoże uniknąć błędów.
Przykład skomplikowanej zagnieżdżenia:
<html>
<body>
<div class="container">
<div class="item">
<h2>Numer 1</h2>
<div class="details">Szczegóły 1</div>
</div>
<div class="item">
<h2>Numer 2</h2>
<div class="details">Szczegóły 2</div>
<div class="additional">
<div class="info">Dodatkowe informacje</div>
</div>
</div>
</div>
</body>
</html>
Wyodrębnianie danych z uwzględnieniem zagnieżdżenia
Aby uniknąć pomyłek, należy znaleźć bardziej specyficzne elementy:
items = soup.select('.container .item')
for item in items:
number = item.find('h2').get_text()
details = item.select_one('.details').get_text()
additional_info = item.select_one('.additional .info')
print(f'Numer: {number}')
print(f'Szczegóły: {details}')
if additional_info:
print(f'Dodatkowe informacje: {additional_info.get_text()}')
print()
Tutaj używamy metody select_one
, która
zwraca tylko pierwszy znaleziony element, aby uniknąć
duplikowania danych z dodatkowych bloków.
5. Praktyczne aspekty i typowe błędy
Pracując ze skomplikowanymi strukturami HTML, łatwo się pomylić
lub natknąć na błędy. Jednym z typowych błędów jest
próba dostępu do nieistniejącego elementu, co prowadzi do
AttributeError
. Aby tego uniknąć, zawsze
sprawdzaj istnienie elementu przed rozpoczęciem pracy z nim.
Ważną rzeczą jest również zrozumienie, że nie zawsze trzeba wyodrębniać dane od razu "na siłę". Czasami warto najpierw przeanalizować strukturę, korzystać z wyników pośrednich i sprawdzać je na bieżąco.
W prawdziwych projektach umiejętności pracy z zagnieżdżonymi strukturami HTML mogą być kluczowe. Znajduje to zastosowanie nie tylko w web scraping, ale również w testowaniu interfejsów webowych, automatyzacji testów, a nawet w analizie danych z bardziej skomplikowanych API, gdzie odpowiedzi mogą mieć sformatowane, zagnieżdżone struktury.
GO TO FULL VERSION