Dopo le classificazioni delle possibili operazioni da compiere viste nelle lezioni precedenti, possiamo avviare un approccio un po' più operativo passando ad attività pratiche come la ricerca di elementi singoli e multipli
Useremo come nave scuola la seguente pagina HTML e ci porremo una serie di obiettivi per imparare a gestire ricerche in base a tag, id e classi.
Ecco il codice HTML:
<!DOCTYPE html>
<html>
<head>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
text-align: left;
padding: 10px;
}
.content {
max-width: 75%;
margin: auto;
}
tr:nth-child(even) {
background-color: #D5F5E3;
}
</style>
</head>
<body>
<div class="content">
<h2>Risultati esame</h2>
<p id="descrizione">Tutti gli allievi che hanno conseguito un voto di almeno <b>18/30</b> possono presentarsi all'esame del prossimo <em>5 marzo</em></p>
<table>
<tr>
<th>Cognome</th>
<th>Nome</th>
<th>Voto</th>
</tr>
<tr>
<td>Rossi</td>
<td>Matteo</td>
<td>16</td>
</tr>
<tr>
<td>Bianchi</td>
<td>Elena</td>
<td>28</td>
</tr>
<tr>
<td>Azzurri</td>
<td>Sonia</td>
<td>25</td>
</tr>
<tr>
<td>Verdi</td>
<td>Ivan</td>
<td>19</td>
</tr>
</table>
</div>
</body>
</html>
e questa è l'anteprima di come appare nel browser.
I nostri obiettivi saranno:
- estrarre la data dell'orale;
- stampare le regole dell'esame;
- calcolare la media dei voti conseguiti all'esame.
Nel seguito, per chiarezza, daremo per assodato di avere a disposizione un driver Selenium già configurato come spiegato nelle lezioni precedenti, basato sul nostro browser preferito.
Gli import
necessari per il seguito sono:
from selenium import webdriver
from selenium.webdriver.common.by import By
from statistics import mean
di cui l'ultimo per il calcolo della media aritmetica.
Ricerca di elementi singoli e multipli. Task n.1: recuperare la data dell'esame
Per risolvere questo problema, notiamo che la data che ci interessa è l'unico testo in corsivo. Perlustrando il codice HTML ne riceviamo conferma, infatti è l'unico contenuto posto tra tag em
. Procediamo alla ricerca di un singolo elemento per tag:
data = driver.find_element(By.TAG_NAME, "em")
print(data.text)
La funzione find_element
restituisce un oggetto di tipo WebElement
e con la proprietà text
ci facciamo estrarre il testo interno. Viene stampato "5 marzo" e questo dimostra che il tutto ha funzionato.
Task n.2: stampa della descrizione
Sulla scorta di quanto visto finora, anche la stampa della descrizione non è affatto complicata. Notiamo che si tratta dell'unico testo incluso all'interno di un tag p
ma è anche dotato di un id
. Potremmo agire su entrambi indifferentemente a livello di risultato ma a livello operativo è sempre meglio prediligere la ricerca via id: una modifica futura alla pagina potrebbe aggiungere un ulteriore paragrafo p
ma non dovrebbe farlo con un id
già esistente.
Notiamo però che questo elemento ha dell'HTML all'interno (un nodo b
con la votazione ed il tag em
che abbiamo usato poc'anzi per estrarre la data) e ciò permetterà di estrarre gli elementi con o senza tag interni ed esterni.
Una volta recuperato il WebElement
mediante id:
descrizione = driver.find_element(By.ID, "descrizione")
possiamo stampare solo il testo senza tag interni o esterni:
print(descrizione.text)
oppure l'intero nodo HTML comprensivo di tag interni e esterni:
print(descrizione.get_attribute('outerHTML'))
il che restituisce:
<p id="descrizione">Tutti gli allievi che hanno conseguito un voto di almeno <b>18/30</b> possono presentarsi all'esame del prossimo <em>5 marzo</em></p>
o, infine, solo l'HTML interno al nodo
print(descrizione.get_attribute('innerHTML'))
che ci fa ottenere:
Tutti gli allievi che hanno conseguito un voto di almeno <b>18/30</b> possono presentarsi all'esame del prossimo <em>5 marzo</em>
Tutto questo può essere fatto con tutti i WebElement
ma quale utilizzare dipende dagli scopi della nostra analisi.
Task n.3: media dei voti
Per questo esercizio, oltre alla conoscenza di Selenium ci servirà un po' di familiarità con Python nonché un briciolo di fantasia. Partiamo da questi presupposti:
- ogni elemento della tabella si trova in un tag
td
; - essendo la struttura regolare ogni tre elementi
td
avremo un voto espresso come numero; - visto che estrarremo più valori con un'unica query non useremo il metodo
find_element
ma la sua versione al "plurale"find_elements
.
Utilizzando tale metodo, ricordiamo che otterremo una lista di WebElement
che all'interno racchiuderà una rappresentazione Python dei singoli nodi. Pertanto dovremo estrarre il testo delle sole celle della colonna a destra e convertirli in interi.
Nel codice che segue otteniamo nella variabile celle
l'elenco delle celle della tabella e con una list comprehension generiamo, da queste un'altra lista fatta di numeri. Notiamo che il ciclo for
itera su celle[2::3]
che significa letteralmente "partiamo dall'elemento di indice 2, proseguiamo fino alla fine saltando tre elementi alla volta": usiamo tre elementi quindi (anche un fattore step oltre agli indici di inizio e fine della selezione) e ciò spiega la coppia di due punti.
celle=driver.find_elements(By.TAG_NAME, "td")
voti=[int(cella.text) for cella in celle[2::3]]
print(f"Media dei voti: {mean(voti)}")
Arriviamo così alla stampa del risultato finale: Media dei voti: 22.