Cel: Napisać prosty scraper, potrafiący pobrać stronę i przeanalizować jej zawartość.
Rozwiązanie
Strona (serwowana lokalnie, python3 -m http.server 8123
):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<p>para1</p>
<p class="c1">para2</p>
<ul id="lst">
<li><a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/">BeautifulSoup docs</a></li>
<li><a href="https://2.python-requests.org/en/master/">Requests docs</a></li>
</ul>
<img src="some_image.png" alt="red square">
</body>
</html>
Scraper:
#!/usr/bin/env python
import requests
import bs4
response = requests.get('http://localhost:8123/sample.html')
assert response.status_code == 200 # nie zaszkodzi sprawdzić, czy się udało
root = bs4.BeautifulSoup(response.text, 'html.parser')
print("Prosty select zwraca wszystkie pasujące elementy:\n", root.select('p'))
print("select_one wybiera pierwszy:\n", root.select_one('p'))
print(".text zwraca zawartość tekstową:\n", root.select_one('p').text)
lst=root.select_one('#lst')
print("Można pobierać obiekty 'ze strukturą':\n", lst)
print("...i odpytywać dalej:\n", lst.select('li a'))
print("Atrybuty są w słowniku attrs:\n", lst.select_one('a').attrs)
print("Można też znajdować elementy po atrybutach:\n", root.select_one('[alt="red square"]'))
Wyniki:
./scrape.py
Prosty select zwraca wszystkie pasujące elementy:
[<p>para1</p>, <p class="c1">para2</p>]
select_one wybiera pierwszy:
<p>para1</p>
.text zwraca zawartość tekstową:
para1
Można pobierać obiekty 'ze strukturą':
<ul id="lst">
<li><a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/">BeautifulSoup docs</a></li>
<li><a href="https://2.python-requests.org/en/master/">Requests docs</a></li>
</ul>
...i odpytywać dalej:
[<a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/">BeautifulSoup docs</a>, <a href="https://2.python-requests.org/en/master/">Requests docs</a>]
Atrybuty są w słowniku attrs:
{'href': 'https://www.crummy.com/software/BeautifulSoup/bs4/doc/'}
Można też znajdować elementy po atrybutach:
<img alt="red square" src="some_image.png"/>
Uwagi
select
wystarcza do zdecydowanej większości prostych zastosowań- Przeglądanie struktury strony w przeglądarce za pomocą narzędzi do inspekcji jest Dobrym Pomysłem.
- Eksperymentowanie w IPythonie jest Dobrym Pomysłem i zazwyczaj Koniecznością
- Zapisywanie stron przed ich sparsowaniem może być Dobrym Pomysłem, przynajmniej w fazie eksperymentowania
- Wyniki pośrednie można piklować
- przy scrapowaniu większej liczby stron warto dodać sleep - systemowy, jeśli
skrypt jest uruchamiany w pętli w shellu, albo
time.sleep
w pythonie.