¿Cómo unir URL absolutas y relativas?

Respuestas:

213

Debe utilizar urlparse.urljoin :

>>> import urlparse
>>> urlparse.urljoin(url1, url2)
'http://127.0.0.1/test1/test4/test6.xml'

Con Python 3 (donde urlparse se renombra a urllib.parse ) puede usarlo de la siguiente manera :

>>> import urllib.parse
>>> urllib.parse.urljoin(url1, url2)
'http://127.0.0.1/test1/test4/test6.xml'
Cédric Julien
fuente
5
¿Cómo lo usamos urljoincon 3 o parámetros de modo o qué biblioteca recomiendan para esto?
Mesut Tasci
@mesuutt intenta hacer un bucle y unir cada parte con la URL previamente unida.
Cédric Julien
2
@ CédricJulien: un bucle simple no funcionará, ya que cualquier ruta con un líder /se "restablecerá" y devolverá el esquema + netloc + lasturl:urlparse.urljoin('http://www.a.com/b/c/d', '/e') => 'http://www.a.com/e'
MestreLion
Si usa urljoin, hay un problema. Por ejemplo, urljoin('http://www.a.com/', '../../b/c.png')el resultado es 'http://www.a.com/../../b/c.png', pero no http://www.a.com/b/c.png. Entonces, ¿hay algún método para conseguirlo http://www.a.com/b/c.png?
bigwind
1
El enlace a la documentación de Python 3 apunta a la documentación de Python 2, debe actualizarse en la respuesta, es docs.python.org/3.6/library/…
Harsh
8

Si su ruta relativa consta de varias partes, debe unirlas por separado, ya urljoinque reemplazaría la ruta relativa, no uniría. La forma más sencilla de hacerlo es usar posixpath.

>>> import urllib.parse
>>> import posixpath
>>> url1 = "http://127.0.0.1"
>>> url2 = "test1"
>>> url3 = "test2"
>>> url4 = "test3"
>>> url5 = "test5.xml"
>>> url_path = posixpath.join(url2, url3, url4, url5)
>>> urllib.parse.urljoin(url1, url_path)
'http://127.0.0.1/test1/test2/test3/test5.xml'

Consulte también: Cómo unir componentes de una ruta cuando está construyendo una URL en Python

pcv
fuente
7
es = ['http://127.0.0.1', 'test1', 'test4', 'test6.xml']
base = ''
map(lambda e: urlparse.urljoin(base, e), es)
Centro comercial Shikhar
fuente
3
Buena forma de respaldar una lista de valores. Sin embargo, puede eliminar su efecto secundario (su variable "base") usando una reducción. reduce(lambda a, b: urlparse.urljoin(a, b), es) Un mapa es list[n] - to -> list[n]A reducir eslist[n] - to -> a calculated value
Peter Perron
4
>>> from urlparse import urljoin
>>> url1 = "http://www.youtube.com/user/khanacademy"
>>> url2 = "/user/khanacademy"
>>> urljoin(url1, url2)
'http://www.youtube.com/user/khanacademy'

Sencillo.

Talha Ashraf
fuente
3

Para Python 3.0+, la forma correcta de unir URL es:

from urllib.parse import urljoin
urljoin('https://10.66.0.200/', '/api/org')
# output : 'https://10.66.0.200/api/org'
srth12
fuente
1

Puedes usar reduce para lograr el método de Shikhar de una manera más limpia.

>>> import urllib.parse
>>> from functools import reduce
>>> reduce(urllib.parse.urljoin, ["http://moc.com/", "path1/", "path2/", "path3/"])
'http://moc.com/path1/path2/path3/'

Tenga en cuenta que con este método, cada fragmento debe tener una barra diagonal al final, sin una barra inclinada inicial (para indicar que se está uniendo un fragmento de ruta). Esto es más correcto / informativo, diciéndole quepath1/ es un fragmento de ruta de URI, y no la ruta completa /path1/o una desconocidapath1 , que podría ser cualquiera (y se trata como una ruta completa).

Si necesita agregar / a un fragmento que no lo tiene, puede hacer:

uri = uri if uri.endswith("/") else f"{uri}/"

Para obtener más información sobre la resolución de URI, Wikipedia tiene algunos buenos ejemplos.

actualizar

Solo se da cuenta de que Peter Perron comentó sobre reducir la respuesta de Shikhar, pero dejaré esto aquí para demostrar cómo se hace.

Ryanjdillon
fuente