Como juntar urls absolutas e relativas?

Respostas:

214

Você deve usar urlparse.urljoin :

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

Com Python 3 (em que urlparse é renomeado para urllib.parse ), você pode usá-lo da seguinte maneira :

>>> import urllib.parse
>>> urllib.parse.urljoin(url1, url2)
'http://127.0.0.1/test1/test4/test6.xml'
Cédric Julien
fonte
5
Como usamos urljoincom 3 parâmetros ou modo ou qual biblioteca você recomenda para isso?
Mesut Tasci
@mesuutt tenta fazer um loop e unir cada parte com a URL previamente unida.
Cédric Julien
2
@ CédricJulien: um loop simples não funcionará, pois qualquer caminho com um líder /irá "zerar" e retornar o esquema + netloc + lasturl:urlparse.urljoin('http://www.a.com/b/c/d', '/e') => 'http://www.a.com/e'
MestreLion
Se estiver usando o urljoin, há um problema. Por exemplo urljoin('http://www.a.com/', '../../b/c.png'),, o resultado é 'http://www.a.com/../../b/c.png', mas não http://www.a.com/b/c.png. Então, existe algum método para obter http://www.a.com/b/c.png?
bigwind
1
O link para a documentação do Python 3 aponta para a documentação do Python 2, ele precisa ser atualizado na resposta, é docs.python.org/3.6/library/…
Harsh
8

Se o seu caminho relativo consiste em várias partes, você deve uni-los separadamente, pois urljoinsubstituiria o caminho relativo, não uniria. A maneira mais fácil de fazer isso é usando 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'

Veja também: Como unir componentes de um caminho ao construir um URL em Python

pcv
fonte
7
es = ['http://127.0.0.1', 'test1', 'test4', 'test6.xml']
base = ''
map(lambda e: urlparse.urljoin(base, e), es)
Shikhar Mall
fonte
3
Boa maneira de apoiar uma lista de valores. Você pode remover seu efeito colateral (sua variável "base") usando uma redução. reduce(lambda a, b: urlparse.urljoin(a, b), es) Um mapa é list[n] - to -> list[n]A redução élist[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'

Simples.

Talha Ashraf
fonte
3

Para python 3.0+, a maneira correta de unir urls é:

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

Você pode usar reducepara alcançar o método de Shikhar de uma forma mais limpa.

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

Observe que, com esse método, cada fragmento deve ter uma barra à direita, sem nenhuma barra à esquerda (para indicar que é um fragmento de caminho sendo unido). Isso é mais correto / informativo, informando que path1/é um fragmento de caminho de URI, e não o caminho completo /path1/ou desconhecido path1, que poderia ser qualquer um (e é tratado como um caminho completo).

Se você precisar adicionar /a um fragmento sem ele, poderá fazer:

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

Para saber mais sobre a resolução de URI, a Wikipedia tem alguns bons exemplos.

atualizar

Só percebo que Peter Perron comentou sobre a redução na resposta de Shikhar, mas vou deixar isso aqui para demonstrar como isso é feito.

Ryanjdillon
fonte