如何加入绝对和相对网址?

问题:如何加入绝对和相对网址?

我有两个网址:

url1 = "http://127.0.0.1/test1/test2/test3/test5.xml"
url2 = "../../test4/test6.xml"

如何获得url2的绝对URL?

I have two urls:

url1 = "http://127.0.0.1/test1/test2/test3/test5.xml"
url2 = "../../test4/test6.xml"

How can I get an absolute url for url2?


回答 0

您应该使用urlparse.urljoin

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

使用Python 3(将urlparse重命名为urllib.parse),您可以按以下方式使用它

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

You should use urlparse.urljoin :

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

With Python 3 (where urlparse is renamed to urllib.parse) you could use it as follow:

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

回答 1

如果您的相对路径由多个部分组成,则必须单独连接它们,因为urljoin它将替换相对路径,而不是将其合并。最简单的方法是使用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'

另请参阅:在Python中构造URL时如何联接路径的组件

If your relative path consists of multiple parts, you have to join them separately, since urljoin would replace the relative path, not join it. The easiest way to do that is to use 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'

See also: How to join components of a path when you are constructing a URL in Python


回答 2

es = ['http://127.0.0.1', 'test1', 'test4', 'test6.xml']
base = ''
map(lambda e: urlparse.urljoin(base, e), es)
es = ['http://127.0.0.1', 'test1', 'test4', 'test6.xml']
base = ''
map(lambda e: urlparse.urljoin(base, e), es)

回答 3

>>> from urlparse import urljoin
>>> url1 = "http://www.youtube.com/user/khanacademy"
>>> url2 = "/user/khanacademy"
>>> urljoin(url1, url2)
'http://www.youtube.com/user/khanacademy'

简单。

>>> from urlparse import urljoin
>>> url1 = "http://www.youtube.com/user/khanacademy"
>>> url2 = "/user/khanacademy"
>>> urljoin(url1, url2)
'http://www.youtube.com/user/khanacademy'

Simple.


回答 4

对于python 3.0+,加入网址的正确方法是:

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

For python 3.0+ the correct way to join urls is:

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

回答 5

您可以使用reduce一种更简洁的方式来实现Shikhar的方法。

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

请注意,使用此方法,每个片段都应具有尾随的正斜杠,而没有前导的正斜杠(以表明它是路径片段的联接)。这更正确/更有意义,告诉您这path1/是URI路径片段,而不是完整路径/path1/或未知路径path1,它可能是(或者被视为完整路径)。

如果需要添加/到缺少该片段的片段,则可以执行以下操作:

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

要了解有关URI解析的更多信息,请参阅Wikipedia。提供了一些很好的示例。

更新

只是注意到彼得·佩隆(Peter Perron)评论了Shikhar回答的减少,但是我将在这里留下来证明它是如何完成的。

You can use reduce to achieve Shikhar’s method in a cleaner fashion.

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

Note that with this method, each fragment should have trailing forward-slash, with no leading forward-slash (to indicate it is a path fragment being joined). This is more correct/informative, telling you that path1/ is a URI path fragment, and not the full path /path1/ or an unknown path1, which could be either (and gets treated as a full path).

If you need to add / to a fragment lacking it, you could do:

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

To learn more about URI resolution, Wikipedia has some nice examples.

update

Just notices Peter Perron commented about reduce on Shikhar’s answer, but I’ll leave this here then to demonstrate how that’s done.