urllib.parse - Divide un URL nei suoi Componenti
Scopo: Divide un URL nei suoi Componenti
Il modulo urllib.parse fornisce funzioni per manipolare gli URL e le parti con le quali sono costituiti, sia per comporli che per decomporli.
Ottenere le Parti
Il valore di ritorno della funzione urlparse() è un oggetto ParseResult che agisce come una tupla di sei elementi.
# urllib_parse_urlparse.py
from urllib.parse import urlparse
url = 'http://netloc/path;param?query=arg#frag'
parsed = urlparse(url)
print(parsed)
Le parti dell'URL disponibili tramite la tupla di interfaccia sono lo schema, la locazione della rete, il percorso, i parametri di segmento del percorso (separati dal percorso da un punto e virgola), query e frammento.
$ python3 urllib_parse_urlparse.py ParseResult(scheme='http', netloc='netloc', path='/path', params='param', query='query=arg', fragment='frag')
Sebbene il valore ritornato agisca come una tupla, in realtà è basato su una namedtuple, una sottoclasse di tuple che supporta l'accesso alle parti dell'URL tramite attributi nominali e numerici. Oltre a essere più facile da usare per gli sviluppatori, l'API offre accesso a parecchi valori non disponibili nell'API di tuple.
# urllib_parse_urlparseattrs.py
from urllib.parse import urlparse
url = 'http://user:pwd@NetLoc:80/path;param?query=arg#frag'
parsed = urlparse(url)
print('schema :', parsed.scheme)
print('loc. di rete:', parsed.netloc)
print('percorso :', parsed.path)
print('parametri :', parsed.params)
print('query :', parsed.query)
print('frammento :', parsed.fragment)
print('nome utene :', parsed.username)
print('password :', parsed.password)
print('nome host :', parsed.hostname)
print('porta :', parsed.port)
username e password sono disponibili se presenti nell'URL elaborato, e impostati a None in caso contrario. hostname ha lo stesso valore di netloc, in caratteri minuscoli e con il valore della porta eliminato, port viene convertito in un intero se presente e a None altrimenti.
$ python3 urllib_parse_urlparseattrs.py schema : http loc. di rete: user:pwd@NetLoc:80 percorso : /path parametri : param query : query=arg frammento : frag nome utene : user password : pwd nome host : netloc porta : 80
La funzione urlsplit() è una alternativa ad urlparse(). Si comporta in maniera leggermente diversa, visto che non separa i parametri dall'URL. Questo è utile per gli URL che seguono le direttive RFC 2396, che supportano parametri per ciascun segmento del percorso.
# urllib_parse_urlsplit.py
from urllib.parse import urlsplit
url = 'http://user:pwd@NetLoc:80/path;param?query=arg#frag'
parsed = urlsplit(url)
print(parsed)
print('schema :', parsed.scheme)
print('loc. di rete:', parsed.netloc)
print('percorso :', parsed.path)
print('query :', parsed.query)
print('frammento :', parsed.fragment)
print('nome utene :', parsed.username)
print('password :', parsed.password)
print('nome host :', parsed.hostname)
print('porta :', parsed.port)
Visto che i parametri non sono estrapolati, l'API di tuple mostrerà solo cinque elementi in luogo di sei, e non c'è l'attributo params.
$ python3 urllib_parse_urlsplit.py SplitResult(scheme='http', netloc='user:pwd@NetLoc:80', path='/path;param', query='query=arg', fragment='frag') schema : http loc. di rete: user:pwd@NetLoc:80 percorso : /path;param query : query=arg frammento : frag nome utene : user password : pwd nome host : netloc porta : 80
Per estrapolare l'identificatore del frammento da un URL, come quando si deve trovare un nome di pagina base per un URL, si usa urldefrag().
# urllib_parse_urldefrag.py
from urllib.parse import urldefrag
original = 'http://netloc/path;param?query=arg#frag'
print('originale:', original)
d = urldefrag(original)
print('url :', d.url)
print('frammento:', d.fragment)
Il valore ritornato è un oggetto DefragResult, basato su namedtuple, che contiene l'URL base e il frammento.
$ python3 urllib_parse_urldefrag.py originale: http://netloc/path;param?query=arg#frag url : http://netloc/path;param?query=arg frammento: frag
Assemblare le Parti
Ci sono parecchi modi per assemblare in una singola stringa le parti di un URL separate. L'oggetto URL separato ha un metodo geturl().
# urllib_parse_geturl.py
from urllib.parse import urlparse
original = 'http://netloc/path;param?query=arg#frag'
print('ORIGINALE :', original)
parsed = urlparse(original)
print('ASSEMBLATO :', parsed.geturl())
geturl() funziona solo con oggetti restituiti da urlparse() ed urlsplit().
$ python3 urllib_parse_geturl.py ORIGINALE : http://netloc/path;param?query=arg#frag ASSEMBLATO : http://netloc/path;param?query=arg#frag
Una tupla normale che contenga stringhe può essere combinata in un URL con urlunparse().
# urllib_parse_urlunparse.py
from urllib.parse import urlparse, urlunparse
original = 'http://netloc/path;param?query=arg#frag'
print('ORIGINALE :', original)
parsed = urlparse(original)
print('ASSEMBLATO :', type(parsed), parsed)
t = parsed[:]
print('TUPLA :', type(t), t)
print('NUOVO :', urlunparse(t))
Mentre l'oggetto ParseResult ritornato da urlparse() può essere usato come tupla, questo esempio crea esplicitamente una nuova tupla per mostrare che urlunparse() funziona anche con le normali tuple.
$ python3 urllib_parse_urlunparse.py
ORIGINALE : http://netloc/path;param?query=arg#frag
ASSEMBLATO : <class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='netloc', path='/path', params='param', query='query=arg', fragment='frag')
TUPLA : <class 'tuple'> ('http', 'netloc', '/path', 'param', 'query=arg', 'frag')
NUOVO : http://netloc/path;param?query=arg#frag
Se l'URL in input comprende anche parti superflue, esse potranno essere ignorate nella ricostruzione dell'URL.
# urllib_parse_urlunparseextra.py
from urllib.parse import urlparse, urlunparse
original = 'http://netloc/path;?#'
print('ORIGINALE :', original)
parsed = urlparse(original)
print('ASSEMBLATO:', type(parsed), parsed)
t = parsed[:]
print('TUPLA :', type(t), t)
print('NUOVO :', urlunparse(t))
In questo caso parameters, query e fragment sono mancanti nell'URL di origine. Il nuovo URL non sembra uguale all'originale, ma, in base agli standard, è equivalente.
$ python3 urllib_parse_urlunparseextra.py
ORIGINALE : http://netloc/path;?#
ASSEMBLATO: <class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='netloc', path='/path', params='', query='', fragment='')
TUPLA : <class 'tuple'> ('http', 'netloc', '/path', '', '', '')
NUOVO : http://netloc/path
Unire
Oltre alla separazione di URL, urllib.urlparse comprende urljoin() per costruire URL assoluti da frammenti relativi.
# urllib_parse_urljoin.py
from urllib.parse import urljoin
print(urljoin('http://www.example.com/path/file.html',
'anotherfile.html'))
print(urljoin('http://www.example.com/path/file.html',
'../anotherfile.html'))
Nell'esempio la porzione relativa del percorso ("../"), viene presa in considerazione quando viene calcolato il secondo URL.
$ python3 urllib_parse_urljoin.py http://www.example.com/path/anotherfile.html http://www.example.com/anotherfile.html
Percorsi non relativi sono gestiti allo stesso modo di os.path.join().
# urllib_parse_urljoin_with_path.py
from urllib.parse import urljoin
print(urljoin('http://www.example.com/path/',
'/subpath/file.html'))
print(urljoin('http://www.example.com/path/',
'subpath/file.html'))
Se il percorso che deve essere unito nell'URL inizia con una barra (/), reimposta il percorso dell'URL al livello superiore, altrimenti viene aggiunto alla fine del percorso dell'URL.
$ python3 urllib_parse_urljoin_with_path.py . http://www.example.com/subpath/file.html http://www.example.com/path/subpath/file.html
Codificare gli Argomenti in Query
Prima di essere aggiunti all'URL, gli argomenti devono essere codificati.
# urllib_parse_urlencode.py
from urllib.parse import urlencode
query_args = {
'q': 'query string',
'foo': 'bar',
}
encoded_args = urlencode(query_args)
print('Codificati:', encoded_args)
La codifica sostituisce i caratteri speciali come gli spazi per assicurarsi che vengano passati al server usando un formato che sia conforme allo standard.
$ python3 urllib_parse_urlencode.py Codificati: foo=bar&q=query+string
Per passare una sequenza di valori usando diverse occorrenze della variabile nella query string, si imposti doseq a True quando si chiama urlencode() .
urllib_parse_urlencode_doseq.py
from urllib.parse import urlencode
query_args = {
'foo': ['foo1', 'foo2'],
}
print('Singola :', urlencode(query_args))
print('Sequenza:', urlencode(query_args, doseq=True))
Il risultato è una query string con diversi valori associati allo stesso nome.
$ python3 urllib_parse_urlencode_doseq.py Singola : foo=%5B%27foo1%27%2C+%27foo2%27%5D Sequenza: foo=foo1&foo=foo2
Per decodificare una query string si usi parse_qs(), oppure parse_qsl().
# urllib_parse_parse_qs.py
from urllib.parse import parse_qs, parse_qsl
encoded = 'foo=foo1&foo=foo2'
print('parse_qs :', parse_qs(encoded))
print('parse_qsl:', parse_qsl(encoded))
Il valore di ritorno da parse_qs() è un dizionario che mappa nomi con valori, mentre parse_qsl() ritorna una lista di tuple che contengono un nome e un valore.
$ python3 urllib_parse_parse_qs.py
parse_qs : {'foo': ['foo1', 'foo2']}
parse_qsl: [('foo', 'foo1'), ('foo', 'foo2')]
I caratteri speciali all'interno degli argomenti della query che potrebbero causare problemi di elaborazione con l'URL lato server sono racchiusi tra virgolette quando passati ad urlencode(). Per eseguire la stessa operazione localmente per generare versioni più sicure delle stringhe si usi quote() o quote_plus() direttamente.
# urllib_parse_quote.py
from urllib.parse import quote, quote_plus, urlencode
url = 'http://localhost:8080/~hellmann/'
print('urlencode() :', urlencode({'url': url}))
print('quote() :', quote(url))
print('quote_plus():', quote_plus(url))
L'implementazione in quote_plus() è più aggressiva verso i caratteri che deve sostituire.
$ python3 urllib_parse_quote.py urlencode() : url=http%3A%2F%2Flocalhost%3A8080%2F%7Ehellmann%2F quote() : http%3A//localhost%3A8080/%7Ehellmann/ quote_plus(): http%3A%2F%2Flocalhost%3A8080%2F%7Ehellmann%2F
Per invertire le operazioni fatte con quote() e quote_plus() si usi rispettivamente unquote() e unquote_plus().
# urllib_parse_unquote.py
from urllib.parse import unquote, unquote_plus
print(unquote('http%3A//localhost%3A8080/%7Ehellmann/'))
print(unquote_plus(
'http%3A%2F%2Flocalhost%3A8080%2F%7Ehellmann%2F'
))
Il valore codificato viene riconvertito come normale stringa URL.
$ python3 urllib_parse_unquote.py http://localhost:8080/~hellmann/ http://localhost:8080/~hellmann/
Vedere anche:
- urllib.parse
- La documentazione della libreria standard per questo modulo
- urllib.request
- Recupera il contenuto di una risorsa identificata da un URL
- RFC 1738
- Sintassi per Uniform Resource Locator (URL)
- RFC 1808
- URL relativi
- RFC 2396
- Sintassi generica per Uniform Resource Identifier (URI)
- RFC 3986
- Sintassi per Uniform Resource Identifier (URI)