Libreria
Web e internet
Pagine web, richieste, email e un piccolo server web.
Funzioni 32
analizza_htmlcodifica_urlcomponi_urlconnessione_attivadecodifica_urldominio_urle_urlhtml_in_testointernet_disponibileinvia_emailleggi_feedleggi_pagina_webmodello_htmlparametri_urlparti_urlproteggi_htmlreindirizzarichiesta_getrichiesta_postrichiesta_webrispondirisposta_webrobots_consentescarica_filescarica_jsonscarica_paginascarica_testoserver_websessione_websito_webspiega_stato_httpurl_assoluto
spiega_stato_http(stato)#
Spiega in italiano un codice di stato HTTP.
stampa(spiega_stato_http(404))richiesta_web(indirizzo, metodo = "GET", parametri = nulla, dati = nulla, json = nulla, intestazioni = nulla, tempo_massimo = 15)#
Una richiesta HTTP completa.
Restituisce un dizionario: stato (200, 404...), riuscita (vero se 2xx), messaggio, spiegazione, testo, json (già trasformato in valori Leo, o nulla), intestazioni, indirizzo. Un codice di errore (404, 500...) NON ferma il programma: controlla riuscita. parametri va nell'indirizzo (?a=1&b=2), json si invia come JSON, dati come modulo web.
variabile voti = [7, 8, 6, 9] # valore di provavariabile r = richiesta_web("https://api.esempio.it/voti", metodo = "POST", json = {"voto": 30})richiesta_get(indirizzo, parametri = nulla, intestazioni = nulla, tempo_massimo = 15)#
Chiede una risorsa (GET).
Come richiesta_web con metodo "GET".
variabile r = richiesta_get("https://api.esempio.it/cerca", parametri = {"q": "Petrarca"})richiesta_post(indirizzo, json = nulla, dati = nulla, intestazioni = nulla, tempo_massimo = 15)#
Invia dati (POST).
Come richiesta_web con metodo "POST".
richiesta_post("https://api.esempio.it/messaggi", json = {"testo": "Ciao"}, intestazioni = {"Authorization": "Bearer ..."})scarica_pagina(indirizzo, tempo_massimo = 15)#
Il testo (o l'HTML) di una pagina web.
Se il sito risponde con un errore (per
variabile html = scarica_pagina("https://www.esempio.it")scarica_testo(indirizzo, tempo_massimo = 15)#
Sinonimo di scarica_pagina.
stampa(scarica_testo("https://www.esempio.it/leggimi.txt"))scarica_json(indirizzo, parametri = nulla, intestazioni = nulla, tempo_massimo = 15)#
Scarica dati JSON come valori Leo.
variabile meteo = scarica_json("https://api.esempio.it/meteo", parametri = {"città": "Roma"})stampa(meteo["temperatura"])scarica_file(indirizzo, percorso = nulla, avanzamento = falso, tempo_massimo = 30)#
Salva su disco un file preso dal web.
Senza percorso usa il nome che il file ha nell'indirizzo. Con avanzamento = vero stampa a che punto è; puoi anche passare una funzione (scaricati, totale) (byte; totale è nulla se il sito non lo dice). Il file compare solo quando è completo. Restituisce il percorso.
scarica_file("https://www.esempio.it/logo.png", "immagini/logo.png", avanzamento = vero)codifica_url(valore)#
Prepara un testo (o un dizionario di parametri) per metterlo in un indirizzo web.
stampa(codifica_url("caffè e latte"))stampa(codifica_url({"q": "Petrarca", "pagina": 2}))decodifica_url(testo)#
Il contrario di codifica_url (%20 torna uno spazio, %C3%A8 torna "è").
stampa(decodifica_url("caff%C3%A8%20e%20latte"))componi_url(indirizzo, parametri)#
Aggiunge i parametri (un dizionario) a un indirizzo, già codificati.
variabile voti = [7, 8, 6, 9] # valore di provastampa(componi_url("https://www.esempio.it/cerca", {"q": "più voti"}))connessione_attiva(sito = "www.google.com", porta = 443, tempo_massimo = 3)#
vero se Internet (o quel sito) risponde.
Non dà mai errore: senza rete restituisce falso.
se non connessione_attiva() allora stampa("Sei offline") fineinternet_disponibile(sito = "www.google.com", porta = 443, tempo_massimo = 3)#
Sinonimo di connessione_attiva.
se internet_disponibile() allora stampa("rete attiva") fineinvia_email(destinatario, oggetto, testo, mittente, server, porta = 587, utente = nulla, password = nulla, tls = vero, html = nulla, copia = nulla, tempo_massimo = 30)#
Invia un'email con un server SMTP.
destinatario e copia possono essere un indirizzo o una lista. Con tls = vero la connessione è cifrata (porta 587 con STARTTLS, porta 465 cifrata da subito). La password non compare mai nei messaggi e non viene inviata senza cifratura (tranne che a questo computer). html aggiunge una versione HTML del messaggio. Restituisce vero.
invia_email("ada@esempio.it", "Ciao", "Il programma è finito!", "leo@esempio.it","smtp.esempio.it", utente = "leo@esempio.it", password = leggi_file("password.txt"))server_web(porta = 8080, pagina = nulla, pagine = nulla, nome = "server")#
Crea un piccolo server web su questo computer.
pagina è il contenuto dell'indirizzo "/" (HTML o testo); pagine un dizionario percorso -> contenuto (un dizionario o una lista diventano JSON). porta = 0 sceglie una porta libera. Poi server.avvia() accende il server e il programma prosegue (serve solo le pagine fisse); server.servi() resta ad ascoltare e manda ogni altra richiesta a quando server.richiesta fai ... fine (i dati sono in evento, la risposta con rispondi).
variabile server = server_web(8080, pagina = "<h1>Ciao!</h1>")rispondi(contenuto = nulla, stato = 200, tipo = nulla, intestazioni = nulla)#
La risposta alla richiesta del server web.
Si usa dentro quando server.richiesta fai ... fine. Un testo che comincia con <html> o <!doctype è una pagina HTML, un dizionario o una lista diventano JSON.
stampa(rispondi("<h1>Ciao {evento["parametri"]["nome"]}</h1>"))rispondi({"errore": "non trovato"}, stato = 404)analizza_html(html, indirizzo = nulla)#
Trasforma un testo HTML in una pagina_html in cui cercare.
Con indirizzo (l'indirizzo da cui viene la pagina) i collegamenti relativi diventano completi.
variabile p = analizza_html("<ul><li>uno</li><li>due</li></ul>")per ogni li in p.cerca("li") fai stampa(li.testo) fineleggi_pagina_web(indirizzo, tempo_massimo = 15)#
Scarica una pagina web e la restituisce come pagina_html.
È scarica_pagina + analizza_html. Se il sito risponde con un errore (404...) ricevi un ErroreFile che lo spiega.
variabile p = leggi_pagina_web("https://www.esempio.it")stampa(p.titolo)html_in_testo(html)#
Toglie i tag da un testo HTML e lascia il testo leggibile, con gli a capo.
Script e stili spariscono, & e simili diventano i caratteri veri, gli elenchi hanno il trattino.
stampa(html_in_testo("<p>Ciao <b>Ada</b> & Leo</p>"))proteggi_html(testo)#
Prepara un testo per metterlo dentro una pagina HTML (< diventa <...).
Serve con i testi scritti dagli utenti: così non possono inserire tag o script nella pagina.
stampa(proteggi_html("<b>3 > 2</b>"))modello_html(modello, dati = nulla)#
Riempie un modello HTML con i dati di un dizionario, proteggendo i testi.
Nel modello: [[nome]] mette il valore protetto (niente tag), [[html nome]] lo mette così com'è, [[utente.nome]] entra nei dizionari; [[per ogni v in voti]] ... [[fine]] ripete il pezzo per ogni elemento; [[se nome]] ... [[altrimenti]] ... [[fine]] lo mostra solo se il valore c'è ([[se non nome]] il contrario). Il modello può venire da un file (leggi_file).
variabile voti = [7, 8, 6, 9] # valore di provamodello_html("<h1>Ciao [[nome]]</h1><ul>[[per ogni v in voti]]<li>[[v]]</li>[[fine]]</ul>", {"nome": "Ada", "voti": [8, 9]})parti_url(indirizzo)#
Divide un indirizzo web nelle sue parti, in un dizionario.
Chiavi: schema ("https"), dominio, porta, percorso, parametri (dizionario), frammento (dopo #), utente.
stampa(parti_url("https://www.esempio.it:8080/cerca?q=leo#fine")["percorso"])dominio_url(indirizzo)#
Il nome del sito di un indirizzo web (senza https://, porta e percorso).
stampa(dominio_url("https://www.esempio.it/notizie?id=3"))parametri_url(indirizzo)#
I parametri di un indirizzo (la parte dopo ?) come dizionario.
Un parametro ripetuto diventa una lista. Funziona anche con la sola parte ?a=1&b=2.
variabile voti = [7, 8, 6, 9] # valore di provastampa(parametri_url("https://www.esempio.it/cerca?q=pi%C3%B9+voti&pagina=2"))url_assoluto(base, collegamento)#
L'indirizzo completo di un collegamento relativo trovato nella pagina base.
stampa(url_assoluto("https://www.esempio.it/notizie/oggi.html", "../foto/gatto.png"))e_url(testo)#
vero se il testo è un indirizzo web completo (http:// o https:// con il nome del sito).
Non dà mai errore.
stampa(e_url("https://www.esempio.it"))stampa(e_url("esempio"))sessione_web(indirizzo_base = nulla, intestazioni = nulla, token = nulla, utente = nulla, password = nulla, tempo_massimo = 15, tentativi = 3)#
Prepara una serie di richieste allo stesso sito o alla stessa API.
La sessione ricorda i cookie (come un browser), manda a ogni richiesta le intestazioni, il token ("Bearer ...") oppure utente e password, aspetta al massimo tempo_massimo secondi e, se il sito è occupato o la rete cade, riprova fino a tentativi volte. Poi: prendi, invia, aggiorna, modifica, cancella, invia_modulo, scarica, pagina, richiesta. I percorsi si aggiungono all'indirizzo base.
variabile api = sessione_web("https://api.esempio.it/v1", token = "abc")variabile utenti = api.prendi("utenti")robots_consente(indirizzo, agente = "Leo", tempo_massimo = 10)#
vero se il file robots.txt del sito permette ai programmi di leggere quell'indirizzo.
Un programma che legge tante pagine di un sito (un "ragno") deve chiederlo prima: è la buona educazione del web. Se il sito non ha robots.txt è tutto permesso; se non risponde, per prudenza no. La risposta resta in memoria 10 minuti.
se robots_consente("https://www.esempio.it/notizie") allora stampa("posso scaricare") fineleggi_feed(sorgente, tempo_massimo = 15)#
Legge un feed di notizie RSS o Atom (da un indirizzo o da un testo XML).
Restituisce un dizionario con titolo, collegamento, descrizione e notizie: una lista di dizionari con titolo, collegamento, data, descrizione (testo senza tag), autore, id.
per ogni n in leggi_feed("https://www.esempio.it/rss")["notizie"] fai stampa(n["titolo"]) finerisposta_web(contenuto = nulla, stato = 200, tipo = nulla, intestazioni = nulla)#
Prepara la risposta di una pagina del sito_web con il codice di stato che vuoi.
tipo può essere "html", "testo", "json", "css", "js", "xml", "csv" o un tipo MIME completo. Senza tipo: un testo che comincia con < è HTML, un dizionario o una lista sono JSON.
funzione gestisci(r) restituisci risposta_web({"errore": "libro non trovato"}, stato = 404) finereindirizza(indirizzo, permanente = falso)#
Risposta del sito_web che manda il browser a un altro indirizzo.
funzione gestisci(r) restituisci reindirizza("/grazie") finesito_web(porta = 8080, titolo = "Il mio sito", aperto_in_rete = falso)#
Crea un piccolo sito web vero su questo computer.
Poi: sito.pagina(percorso, contenuto) aggiunge una pagina (un testo HTML, un dizionario che diventa JSON, o una funzione che riceve la richiesta); sito.file_statici(...) serve una cartella (immagini, CSS); sito.servi() accende il sito e risponde. Il sito si apre solo da questo computer; con aperto_in_rete = vero anche dagli altri della stessa rete (Wi-Fi di casa). porta = 0 sceglie una porta libera.
variabile sito = sito_web(8080)sito.pagina("/", "<h1>Benvenuti!</h1>")Oggetto «server_web»
Piccolo server web su questo computer (127.0.0.1).
Le pagine fisse (pagine) le serve un thread secondario, anche mentre il programma fa altro (avvia). Le richieste per il codice Leo (quando server.richiesta o una funzione gestore) vengono invece passate al thread del programma da servi: il codice Leo gira sempre in un solo thread.
| Proprietà | Significato |
|---|---|
attivo | |
indirizzo | |
porta | |
richieste_servite |
.aggiungi_pagina(percorso, contenuto)#
Aggiunge (o sostituisce) una pagina fissa.
server.aggiungi_pagina("/info", "<p>Fatto con Leo</p>").avvia()#
Accende il server senza fermare il programma (serve le pagine fisse).
L'indirizzo da aprire nel browser è server.indirizzo.
.ferma()#
Spegne il server (dentro quando server.richiesta termina servi dopo questa risposta).
.servi(gestore = nulla, richieste = nulla, secondi = nulla)#
Ascolta e risponde alle richieste.
Ogni richiesta (tranne le pagine fisse) va a quando server.richiesta fai ... fine (scritto PRIMA di servi), oppure alla funzione gestore(richiesta) se la passi. La richiesta ha percorso, metodo, parametri, corpo, json, intestazioni, cliente. Si ferma dopo richieste richieste, dopo secondi secondi, con server.ferma() o con Ctrl+C. Restituisce quante richieste ha servito.
server.servi(richieste = 10)Oggetto «elemento_html»
Un elemento di una pagina HTML (<a>, <div>...) con i suoi figli.
| Proprietà | Significato |
|---|---|
attributi | |
classi | |
figli | |
genitore | |
html | |
html_interno | |
id | |
tag | |
testo | Il testo dell'elemento su una riga (spazi compattati, senza script e stili). |
.attributo(nome, predefinito = nulla)#
Il valore di un attributo (href, src, class...).
Se l'attributo non c'è restituisce predefinito.
stampa(collegamento.attributo("href")).cerca(selettore, testo = nulla)#
Tutti gli elementi che corrispondono al selettore CSS.
Il selettore può essere un tag ("a"), una classe (".notizia"), un id ("#menu"), una combinazione ("div.notizia > h2", "ul li", "a[href^=https]") o più selettori separati da virgole ("h1, h2"). Con testo tiene solo gli elementi che contengono quel testo.
per ogni t in pagina.cerca("h2.titolo") fai stampa(t.testo) fine.primo(selettore, testo = nulla)#
Il primo elemento che corrisponde al selettore, o nulla.
variabile prezzo = pagina.primo(".prezzo")se prezzo != nulla allora stampa(prezzo.testo) fineOggetto «pagina_html»
Una pagina HTML analizzata, in cui si può cercare.
| Proprietà | Significato |
|---|---|
html | |
indirizzo | |
lingua | |
testo | |
titolo |
.cerca(selettore, testo = nulla)#
Tutti gli elementi che corrispondono al selettore CSS.
Il selettore può essere un tag ("a"), una classe (".notizia"), un id ("#menu"), una combinazione ("div.notizia > h2", "ul li", "a[href^=https]") o più selettori separati da virgole ("h1, h2"). Con testo tiene solo gli elementi che contengono quel testo.
per ogni t in pagina.cerca("h2.titolo") fai stampa(t.testo) fine.collegamenti(contiene = nulla)#
Tutti i collegamenti (<a href>) come dizionari testo e indirizzo.
Gli indirizzi sono completi (relativi alla pagina). Senza doppioni. Con contiene tiene solo quelli il cui indirizzo contiene quel testo.
per ogni c in pagina.collegamenti() fai stampa(c["testo"], "->", c["indirizzo"]) fine.immagini()#
Tutte le immagini come dizionari indirizzo, descrizione (il testo alt), larghezza, altezza.
per ogni img in pagina.immagini() fai stampa(img["indirizzo"]) fine.meta()#
Le informazioni <meta> della pagina (descrizione, autore, parole chiave...) come dizionario.
stampa(pagina.meta().ottieni("description", "nessuna descrizione")).moduli()#
I moduli (<form>) della pagina: azione (indirizzo completo), metodo e campi (nome -> valore).
Utile con sessione.invia_modulo(...): i campi nascosti (per
variabile m = pagina.moduli()[0]stampa(m["campi"]).primo(selettore, testo = nulla)#
Il primo elemento che corrisponde al selettore, o nulla.
variabile prezzo = pagina.primo(".prezzo")se prezzo != nulla allora stampa(prezzo.testo) fine.tabelle(converti_numeri = vero)#
Le tabelle HTML della pagina come tabelle di dati.
Ogni tabella è una lista di righe: se la tabella ha la riga di intestazione (<th>) ogni riga è un dizionario colonna -> valore (come leggi_tabella), altrimenti una lista. I numeri diventano numeri (anche "3,5").
variabile classifica = pagina.tabelle()[0]stampa(classifica[0]["Squadra"]).titoli()#
I titoli della pagina (<h1>...<h6>) come dizionari livello e testo, in ordine.
È l'indice della pagina.
per ogni t in pagina.titoli() fai stampa(" " * (t["livello"] - 1) + t["testo"]) fineOggetto «sessione_web»
Una serie di richieste allo stesso sito, con intestazioni, cookie e accesso in comune.
| Proprietà | Significato |
|---|---|
cookie | |
indirizzo_base | |
intestazioni | |
ultima_risposta |
.aggiorna(percorso, dati = nulla, parametri = nulla)#
Sostituisce una risorsa (PUT) con i nuovi dati.
api.aggiorna("libri/3", {"titolo": "Pinocchio", "anno": 1883}).cancella(percorso, parametri = nulla)#
Elimina una risorsa (DELETE) e restituisce la risposta del sito.
api.cancella("libri/3").imposta_intestazione(nome, valore)#
Aggiunge o cambia un'intestazione per tutte le richieste successive (nulla la toglie).
api.imposta_intestazione("Accept-Language", "it").invia(percorso, dati = nulla, parametri = nulla)#
Crea una risorsa (POST); dizionari e liste vanno come JSON.
Restituisce la risposta del sito (JSON già trasformato, o il testo).
variabile nuovo = api.invia("libri", {"titolo": "Pinocchio", "anno": 1883}).invia_modulo(percorso, campi = nulla, file = nulla)#
Invia un modulo web (POST), anche con dei file da caricare.
campi è un dizionario nome -> valore; file un dizionario nome del campo -> percorso del file sul computer (oppure solo il percorso: il campo si chiama "file").
sito.invia_modulo("carica", {"titolo": "Gita"}, file = {"foto": "gita.jpg"}).modifica(percorso, dati = nulla, parametri = nulla)#
Cambia solo alcuni campi di una risorsa (PATCH).
api.modifica("libri/3", {"letto": vero}).pagina(percorso = "", parametri = nulla)#
Scarica una pagina (con i cookie della sessione) come pagina_html.
variabile p = sito.pagina("notizie")stampa(p.titolo).prendi(percorso = "", parametri = nulla)#
Legge una risorsa (GET) e restituisce i dati (JSON già trasformato, o il testo).
Se il sito risponde con un errore ricevi un ErroreFile che lo spiega.
variabile libri = api.prendi("libri", parametri = {"autore": "Collodi"}).richiesta(percorso, metodo = "GET", parametri = nulla, dati = nulla, intestazioni = nulla)#
Una richiesta completa che non si ferma mai per un codice di errore.
Restituisce un dizionario come richiesta_web: stato, riuscita, spiegazione, testo, json, intestazioni, indirizzo. dati: un dizionario o una lista vanno come JSON.
variabile r = api.richiesta("utenti/7", metodo = "DELETE")stampa(r["stato"]).scarica(percorso, file = nulla, avanzamento = falso)#
Salva su disco un file preso dal sito (con i cookie e l'accesso della sessione).
Con avanzamento = vero scrive la percentuale; puoi anche passare una funzione (scaricati, totale). Il file compare solo quando è completo. Restituisce il percorso.
api.scarica("rapporti/2024.pdf", "rapporto.pdf", avanzamento = vero)Oggetto «risposta_web»
Una risposta preparata per un sito: contenuto, stato e intestazioni.
| Proprietà | Significato |
|---|---|
intestazioni | |
stato | |
testo | |
tipo |
Oggetto «sito_web»
Un piccolo sito: pagine fisse, pagine fatte da funzioni Leo, file statici.
| Proprietà | Significato |
|---|---|
attivo | |
indirizzo | |
pagine | |
porta | |
richieste_servite | |
titolo |
.avvia()#
Accende il sito senza fermare il programma (servono subito le pagine fisse e i file).
Le pagine fatte da una funzione rispondono solo mentre il programma è dentro sito.servi().
sito.avvia()stampa("Apri", sito.indirizzo).ferma()#
Spegne il sito (dentro una pagina fatta da una funzione, servi finisce dopo questa risposta).
sito.pagina("/spegni", funzione (r) sito.ferma() fine).file_statici(cartella, percorso = "/")#
Pubblica i file di una cartella del computer (immagini, CSS, pagine HTML già pronte).
I file nascosti (che cominciano con il punto) e quelli fuori dalla cartella non si vedono mai.
sito.file_statici("immagini", "/immagini").pagina(percorso, contenuto, metodo = "GET")#
Aggiunge una pagina al sito.
contenuto può essere un testo (HTML se comincia con <), un dizionario o una lista (risposta JSON, per fare un'API), una risposta_web oppure una funzione che riceve la richiesta (percorso, metodo, parametri, modulo, json, cookie...) e restituisce il contenuto. Nel percorso le parti tra < e > sono variabili: con "/libri/<numero>" la funzione trova richiesta["parametri"]["numero"]. metodo può essere "POST" per i moduli.
sito.pagina("/saluta/<nome>", funzione (r) restituisci "<h1>Ciao {r["parametri"]["nome"]}!</h1>" fine).servi(richieste = nulla, secondi = nulla, apri_browser = falso)#
Accende il sito e risponde alle richieste finché non lo fermi.
Si ferma dopo richieste richieste, dopo secondi secondi, con sito.ferma() o con Ctrl+C. Con apri_browser = vero apre la pagina nel browser. Restituisce quante richieste ha servito.
sito.servi(apri_browser = vero)