-
Notifications
You must be signed in to change notification settings - Fork 84
Beautiful Soup
Beautiful Soup yra Python biblioteka, duomenų traukimui iš HTML ir XML. BS moka naviguoti tekste pagal html blokus, klases, id ar kitus atributus. Vienas iš populiariausių įrankių web scraping užduotims atlikti. Dokumentaciją rasite čia. Diegiasi pip install beautifulsoup4.
from bs4 import BeautifulSoup
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>First HTML Page</title>
</head>
<body>
<div id="first">
<h3 data-example="yes">hi</h3>
<p>more text.</p>
</div>
<ol>
<li class="special">This list item is special.</li>
<li class="special">This list item is also special.</li>
<li>This list item is not special.</li>
</ol>
<div data-example="yes">bye</div>
</body>
</html>
"""
soup = BeautifulSoup(html, "html.parser")
print(type(soup))
Importuojame BeautifulSoup klasę, ir iš HTML stringo išsiverdame buljoną :) Dabar, turėdami soup objektą, galime naudotis jo funkcionalumu duomenų traukimui. Pvz.:
print(soup.body)
# <body>
# <div id="first">
# <h3 data-example="yes">hi</h3>
# <p>more text.</p>
# </div>
# <ol>
# <li class="special">This list item is special.</li>
# <li class="special">This list item is also special.</li>
# <li>This list item is not special.</li>
# </ol>
# <div data-example="yes">bye</div>
# </body>
Ištraukiame body bloką. Arba:
print(soup.body.div)
# <div id="first">
# <h3 data-example="yes">hi</h3>
# <p>more text.</p>
# </div>
Gavome pirmą div bloką bloke body.
Lygiai tą patį gautumėm panaudoję .find() metodą:
print(soup.find('div'))
# <div id="first">
# <h3 data-example="yes">hi</h3>
# <p>more text.</p>
# </div>
find() ištraukia pirmą sutampančią atkarpą, find_all išgaudo visas ir grąžina sąraše:
print(soup.find_all('div'))
# [<div id="first">
# <h3 data-example="yes">hi</h3>
# <p>more text.</p>
# </div>, <div data-example="yes">bye</div>]
Elementus taip pat galime traukti pagal bloko atributus, pvz id, class ir pan.:
print(soup.find_all(class_='special'))
# [<li class="special">This list item is special.</li>, <li class="special">This list item is also special.</li>]
Atkreipkite dėmesį, kaip užrašytas class_ parametras
jeigu naudotumėm su unikaliais atributais, pvz id (HTML dokumente gali būti tik 1 unikalus id), analogiškai galime panaudoti metodą .find().
Jeigu ieškome pagal 'custom' atributus, pvz šiame dokumente data-example="yes", naudosime tokią techniką:
print(soup.find_all(attrs={'data-example': 'yes'}))
# [<h3 data-example="yes">hi</h3>, <div data-example="yes">bye</div>]
Susipažinti su CSS selektoriais galite čia
Naudosime metodą .select():
print(soup.select('#first'))
# [<div id="first">
# <h3 data-example="yes">hi</h3>
# <p>more text.</p>
# </div>]
Naudojant select(), visada gausime sąrašą, netgi jeigu jame tik vienas narys, todėl norėdami pasiekti konkretų jo narį turėsite nurodyti indeksą.
Dar keletas pavyzdžių:
print(soup.select('.special'))
# [<li class="special">This list item is special.</li>, <li class="special">This list item is also special.</li>]
print(soup.select('div'))
# [<div id="first">
# <h3 data-example="yes">hi</h3>
# <p>more text.</p>
# </div>, <div data-example="yes">bye</div>]
print(soup.select('[data-example]'))
# [<h3 data-example="yes">hi</h3>, <div data-example="yes">bye</div>]
Kuomet norime ištraukti patį tekstą iš HTML bloko, darome taip:
element = soup.select('.special')[0]
print(element.get_text())
# This list item is special.
Galime ir praiteruoti:
elements = soup.select('.special')
for element in elements:
print(element.get_text())
# This list item is special.
# This list item is also special.
norėdami gauti blokų pavadinimus pagal (pvz) klasę, darysime taip:
elements = soup.select('.special')
for element in elements:
print(element.name)
# li
# li
norėdami išgauti bloko atributus, naudosime .attrs:
elements = soup.select('meta')
print(elements[0].attrs)
# {'charset': 'UTF-8'}
Atributų reikšmes galime sužinoti tokiu būdu:
attribute = soup.select('div')[0]['id']
print(attribute)
# first
arba:
attribute = soup.find('div')['id']
print(attribute)
# first
print(soup.div.contents)
# ['\n', <h3 data-example="yes">hi</h3>, '\n', <p>more text.</p>, '\n']
būdas turi trūkumą, nes į sąrašą įtraukia naujos eilutės simbolius. Panagrinėkime html atkarpą:
<body>
<div id="first">
<h3 data-example="yes">hi</h3>
<p>more text.</p>
</div>
<ol>
<li class="special">This list item is special.</li>
<li class="special">This list item is also special.</li>
<li>This list item is not special.</li>
</ol>
<div data-example="yes">bye</div>
</body>
body turi tris 'vaikus' - div, ol, div, vienas kitam jie yra 'broliai'(siblings), nes yra viename hierarchijos lygyje.
li = soup.find('li')
print(li.next_sibling.next_sibling) #todėl, kad '\n' užskaito už siblingą
# <li class="special">This list item is also special.</li>
suradome sekantį pirmojo li elemento 'brolį' (analogiškai galima dirbti su previous_sibling)
print(li.parent)
# <ol>
# <li class="special">This list item is special.</li>
# <li class="special">This list item is also special.</li>
# <li>This list item is not special.</li>
# </ol>
išsiaiškinome, kas tėvas.
print(li.parent.parent)
# <body>
# <div id="first">
# <h3 data-example="yes">hi</h3>
# <p>more text.</p>
# </div>
# <ol>
# <li class="special">This list item is special.</li>
# <li class="special">This list item is also special.</li>
# <li>This list item is not special.</li>
# </ol>
# <div data-example="yes">bye</div>
# </body>
sužinojome, kas senelis :)
Iki šiol navigavome per Tags, dabar pabandykime per metodus:
li = soup.find('li')
print(li.find_next_sibling())
# <li class="special">This list item is also special.</li>
li = soup.find('li')
print(li.find_next_siblings())
# [<li class="special">This list item is also special.</li>, <li>This list item is not special.</li>]
# reikia suteikti klasę not-special paskutiniam li elementui
li = soup.find('li')
print(li.find_next_sibling(class_='not-special'))
# <li class="not-special">This list item is not special.</li>
naviguojant galime kurti tokias ir panašias grandines:
li = soup.find('li')
res = li.find_parent().find_previous_sibling()['id']
print(res)
# first
res = soup.body.next_element.next_element.next_element.next_element.get_text()
print(res)
# hi
© Donatas Noreika ir Jotautas Treigys
Dekoratoriai
Iteratoriai ir generatoriai
RegEx
Pillow
NumPy
Pandas
- Pandas I
- Užduotys I
- Atsakymai I
- Pandas II
- Užduotys II
- Atsakymai II
- Pandas III
- Užduotys III
- Atsakymai III
Seaborn
Mašininis mokymasis
- 1 Tiesinės regresijos modelis
- 1 Užduotis
- 1 Atsakymas
- 2 Modeliai - klasifikatoriai
- 2 Užduotis
- 2 Atsakymas
- 3 Modeliai praktikoje
- 3 Užduotis (atnaujinta), atsakymas
- 3 Užduotis
- 3 Atsakymas (kodas su komentarais)
Requests, JSON, API
Web Scraping (Beautiful Soup)
Duomenų bazės
- SQL 1
- Užduotys
- Atsakymai
- SQL 2
- Užduotys
- Atsakymai
- SQL 3
- Užduotys
- Atsakymai
- SQL 4
- Užduotis
- SQL per Python
- Užduotis
- ORM 1
- Užduotys
- ORM 2
- Užduotis
- Atsakymas
Flask
- Įžanga
- Užduotys
- I dalis
- Užduotis
- I dalies kodas (atsakymas)
- II dalis
- Užduotis
- Atsakymas (kodas)
- III dalis
- Užduotis
- Atsakymas
- IV dalis
- Užduotis
- Atsakymas
- Flask Many2one, CRUD
- Flask One2many, many2many CRUD
- Flask: REST API kūrimas
- Flask: API su One2many (kodas)
- Flask: vartotojai
- Flask: nuotraukos pridėjimas, admin puslapis, puslapiavimas
- Flask: password reset, error pages
- Flask: projekto sutvarkymas
- Flask diegimas į serverį
Django
- 1. Įžanga, Modeliai
- 2. Administratoriaus svetainė
- 3. Šablonai
- 4. Views
- 5. Puslapiavimas, Paieška, Nuotraukos
- 6. Autorizacija
- 7. Vartotojai II, HTML laukai
- 8. Registracija, Formos
- 9. Vartotojo profilis
- 10. Create, Update, Delete rodinių klasės
- 11. Vertimai
- Užduotis: Autoservisas
- Biblioteka: kodas iki 6-tos dalies
- Biblioteka: kodas nuo 6-tos dalies
- Django diegimas į serverį
- Django diegimas į serverį 2
Django REST
Odoo
- Kurso programa: projektų valdymas
- 1 pamoka
- 2 pamoka
- 3 pamoka
- 4 pamoka
- 5 pamoka
- 6 pamoka
- 7 pamoka
- 8 pamoka
- 9 pamoka
Linux