为什么 python 的 urljoin 没有按预期工作?

Why does python's urljoin not work as expected?

使用 python 3.8 我想将 URL 的两个部分合二为一。这是一个例子:

domain = "https://some.domain.ch/myportal#/"
urllib.parse.urljoin(domain, "test1")

这给出了输出

'https://some.domain.ch/test1'

但我希望输出

'https://some.domain.ch/myportal#/test1'

问才明白。

作为解决方法,我将使用

domain + "test1"
urllib.parse.urlparse(domain)
ParseResult(scheme='https', netloc='some.domain.ch', path='/myportal', params='', query='', fragment='/')

问题是您的路径中有一个 #,根据 urllib.parse 遵循的规范 RFC-3986,这是不正确的。

有关 URL 的各部分的图表,请参阅 §3 :

         foo://example.com:8042/over/there?name=ferret#nose
         \_/   \______________/\_________/ \_________/ \__/
          |           |            |            |        |
       scheme     authority       path        query   fragment

path定义在§3.3中。 你的是/myportal,跟规则有关

path-absolute = "/" [ segment-nz *( "/" segment ) ]
...
segment-nz    = 1*pchar

pchar§A中定义:

   pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
...
   pct-encoded   = "%" HEXDIG HEXDIG

   unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
...
   sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
                 / "*" / "+" / "," / ";" / "="

# 不能是 pchar 所以 path 到此为止。

如果不需要,请删除 # :

>>> import urllib.parse
>>> urllib.parse.urljoin("https://some.domain.ch/myportal/", "test1")
'https://some.domain.ch/myportal/test1'

或者percent-encode吧:

>>> urllib.parse.quote("#")
'%23'
>>> urllib.parse.urljoin("https://some.domain.ch/myportal%23/", "test1")
#                                                        ^^^
'https://some.domain.ch/myportal%23/test1'