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)