urllib.parse — Dividir URLs en componentes¶
Propósito: | Divide URLs en componentes |
---|
El módulo urllib.parse
proporciona funciones para manipular URLs y sus
componentes, para descomponerlas o construirlas.
Análisis¶
El valor de retorno de la función urlparse()
es un objeto ParseResult
que actúa como un tuple
con seis elementos.
from urllib.parse import urlparse
url = 'http://netloc/path;param?query=arg#frag'
parsed = urlparse(url)
print(parsed)
Las partes de la URL disponibles a través de la interfaz de la tupla son los parámetros de esquema, ubicación de red, ruta, segmento de ruta (separados de la ruta por un punto y coma), consulta y fragmento.
$ python3 urllib_parse_urlparse.py
ParseResult(scheme='http', netloc='netloc', path='/path',
params='param', query='query=arg', fragment='frag')
Aunque el valor de retorno actúa como una tupla, realmente se basa en un
namedtuple
, una subclase de tuple
que soporta acceder a las partes de
la URL a través de atributos nombrados, así como índices. Además de ser más
fácil de usar para el programador, la interfaz de programación de atributo
también ofrece acceso a varios valores no disponibles en la interfaz de
programación tuple
.
from urllib.parse import urlparse
url = 'http://user:pwd@NetLoc:80/path;param?query=arg#frag'
parsed = urlparse(url)
print('scheme :', parsed.scheme)
print('netloc :', parsed.netloc)
print('path :', parsed.path)
print('params :', parsed.params)
print('query :', parsed.query)
print('fragment:', parsed.fragment)
print('username:', parsed.username)
print('password:', parsed.password)
print('hostname:', parsed.hostname)
print('port :', parsed.port)
El username
y password
están disponibles cuando están presentes en la
URL de entrada, y se establece en None
cuando no. El hostname
tiene el
mismo valor que netloc
, en minúsculas y con el valor de puerto eliminado.
Y el port
se convierte en un entero cuando está presente y None
cuando
no está presente.
$ python3 urllib_parse_urlparseattrs.py
scheme : http
netloc : user:pwd@NetLoc:80
path : /path
params : param
query : query=arg
fragment: frag
username: user
password: pwd
hostname: netloc
port : 80
La función urlsplit()
es una alternativa a urlparse()
. Se comporta un
poco diferente, porque no divide los parámetros de la URL. Esto es útil para
las siguientes URLs RFC 2396, que admite parámetros para cada segmento de la
ruta.
from urllib.parse import urlsplit
url = 'http://user:pwd@NetLoc:80/p1;para/p2;para?query=arg#frag'
parsed = urlsplit(url)
print(parsed)
print('scheme :', parsed.scheme)
print('netloc :', parsed.netloc)
print('path :', parsed.path)
print('query :', parsed.query)
print('fragment:', parsed.fragment)
print('username:', parsed.username)
print('password:', parsed.password)
print('hostname:', parsed.hostname)
print('port :', parsed.port)
Como los parámetros no están divididos, la interfaz de programación de la tupla
mostrará cinco elementos en lugar de seis, y no hay ningún atributo params
.
$ python3 urllib_parse_urlsplit.py
SplitResult(scheme='http', netloc='user:pwd@NetLoc:80',
path='/p1;para/p2;para', query='query=arg', fragment='frag')
scheme : http
netloc : user:pwd@NetLoc:80
path : /p1;para/p2;para
query : query=arg
fragment: frag
username: user
password: pwd
hostname: netloc
port : 80
Para simplemente quitar el identificador del fragmento de una URL, como cuando
para encontrar un nombre de página base desde una URL, usa urldefrag()
.
from urllib.parse import urldefrag
original = 'http://netloc/path;param?query=arg#frag'
print('original:', original)
d = urldefrag(original)
print('url :', d.url)
print('fragment:', d.fragment)
El valor de retorno es un DefragResult
, basado en namedtuple
, que
contiene la URL base y el fragmento.
$ python3 urllib_parse_urldefrag.py
original: http://netloc/path;param?query=arg#frag
url : http://netloc/path;param?query=arg
fragment: frag
Combinar¶
Hay varias formas de ensamblar las partes de una URL dividida juntos en una sola
cadena. El objeto URL analizado tiene un método geturl()
.
from urllib.parse import urlparse
original = 'http://netloc/path;param?query=arg#frag'
print('ORIG :', original)
parsed = urlparse(original)
print('PARSED:', parsed.geturl())
geturl()
solo funciona en el objeto devuelto por urlparse()
o
urlsplit()
.
$ python3 urllib_parse_geturl.py
ORIG : http://netloc/path;param?query=arg#frag
PARSED: http://netloc/path;param?query=arg#frag
Una tupla regular que contiene cadenas se puede combinar en una URL con
urlunparse()
.
from urllib.parse import urlparse, urlunparse
original = 'http://netloc/path;param?query=arg#frag'
print('ORIG :', original)
parsed = urlparse(original)
print('PARSED:', type(parsed), parsed)
t = parsed[:]
print('TUPLE :', type(t), t)
print('NEW :', urlunparse(t))
Mientras que el ParseResult
devuelto por urlparse()
puede ser utilizado
como tupla, este ejemplo crea explícitamente una tupla nueva para mostrar que
urlunparse()
también funciona con tuplas normales.
$ python3 urllib_parse_urlunparse.py
ORIG : http://netloc/path;param?query=arg#frag
PARSED: <class 'urllib.parse.ParseResult'>
ParseResult(scheme='http', netloc='netloc', path='/path',
params='param', query='query=arg', fragment='frag')
TUPLE : <class 'tuple'> ('http', 'netloc', '/path', 'param',
'query=arg', 'frag')
NEW : http://netloc/path;param?query=arg#frag
Si la URL de entrada incluía partes superfluas, esas pueden ser eliminadas de la URL reconstruida.
from urllib.parse import urlparse, urlunparse
original = 'http://netloc/path;?#'
print('ORIG :', original)
parsed = urlparse(original)
print('PARSED:', type(parsed), parsed)
t = parsed[:]
print('TUPLE :', type(t), t)
print('NEW :', urlunparse(t))
En este caso, parameters
, query
y fragment
falta todos en la URL
original. La nueva URL no se ve igual que la original, pero es equivalente
según la norma.
$ python3 urllib_parse_urlunparseextra.py
ORIG : http://netloc/path;?#
PARSED: <class 'urllib.parse.ParseResult'>
ParseResult(scheme='http', netloc='netloc', path='/path',
params='', query='', fragment='')
TUPLE : <class 'tuple'> ('http', 'netloc', '/path', '', '', '')
NEW : http://netloc/path
Unir¶
Además de analizar las URL, urlparse
incluye urljoin()
para
construir URLs absolutas a partir de fragmentos relativos.
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'))
En el ejemplo, se toma la parte relativa de la ruta ("../"
) en cuenta
cuando se calcula la segunda URL.
$ python3 urllib_parse_urljoin.py
http://www.example.com/path/anotherfile.html
http://www.example.com/anotherfile.html
Las rutas no relativas se manejan de la misma manera que por
os.path.join()
.
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'))
Si la ruta que se une a la URL comienza con una barra (/
), se restablece la
ruta de la URL al nivel superior. Si no comienza con un barra, se anexa al
final de la ruta de la URL.
$ python3 urllib_parse_urljoin_with_path.py
http://www.example.com/subpath/file.html
http://www.example.com/path/subpath/file.html
Codificar argumentos de consulta¶
Antes de que se puedan agregar argumentos a una URL, deben codificarse.
from urllib.parse import urlencode
query_args = {
'q': 'query string',
'foo': 'bar',
}
encoded_args = urlencode(query_args)
print('Encoded:', encoded_args)
La codificación reemplaza los caracteres especiales como los espacios para garantizar que se pasan al servidor utilizando un formato que cumple con el estándar.
$ python3 urllib_parse_urlencode.py
Encoded: q=query+string&foo=bar
Para pasar una secuencia de valores usando apariciones separadas de la variable
en la cadena de consulta, establezca doseq
en True
al llamar
urlencode()
.
from urllib.parse import urlencode
query_args = {
'foo': ['foo1', 'foo2'],
}
print('Single :', urlencode(query_args))
print('Sequence:', urlencode(query_args, doseq=True))
El resultado es una cadena de consulta con varios valores asociados con el mismo nombre.
$ python3 urllib_parse_urlencode_doseq.py
Single : foo=%5B%27foo1%27%2C+%27foo2%27%5D
Sequence: foo=foo1&foo=foo2
Para decodificar la cadena de consulta, usa parse_qs()
o parse_qsl()
.
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))
El valor de retorno de parse_qs()
es un diccionario que asigna nombres a
valores, mientras que parse_qsl()
devuelve una lista de tuplas que
contienen un nombre y un valor.
$ python3 urllib_parse_parse_qs.py
parse_qs : {'foo': ['foo1', 'foo2']}
parse_qsl: [('foo', 'foo1'), ('foo', 'foo2')]
Caracteres especiales dentro de los argumentos de consulta que podrían causar
problemas en el análisis de la URL en el lado del servidor se «citan» cuando se
pasan a urlencode()
. Para citarlos localmente para hacer versiones seguras
de las cadenas, usa las funciones quote()
o quote_plus()
directamente.
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))
La implementación de la cita en quote_plus()
es más agresiva con los
caracteres que reemplaza.
$ 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
Para revertir las operaciones de la cita, usa unquote()
o
unquote_plus()
, según corresponda.
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'
))
El valor codificado se convierte de nuevo a una URL de cadena normal.
$ python3 urllib_parse_unquote.py
http://localhost:8080/~hellmann/
http://localhost:8080/~hellmann/
Ver también
- Documentación de la biblioteca estándar para urllib.parse
urllib.request
– Recuperar los contenidos de un recurso. identificado por una URL.- RFC 1738 – Sintaxis Uniform Resource Locator (URL)
- RFC 1808 – URLs relativos
- RFC 2396 – Sintaxis genérica Uniform Resource Identifier (URI)
- RFC 3986 – Sintaxis Uniform Resource Identifier (URI)