urllib.parse(和它的 Python 2 相似物) 的一个好处是,它可以处理部分 URL 和完整 URL。这很方便,因为在 web 服务器的环境中,你可能会得到部分 URL 或完整的 URL,你想对它们进行解码,以便提取各种信息 (主要是路径,因为这是你能可靠地指望存在于部分 URL 中的所有信息)。 然而,一旦你窥探到 URL 的秘密,它就是一件棘手的事情;例如,见URLs。这很复杂....一个适当的URL解析器需要处理这种全部的复杂性,这意味着它隐藏了一个关于相对URL将如何解释的惊喜。
例如,假设你正在解析一个ApacheREQUEST_URI,以提取请求的路径。你必须实际解析请求的URI才能得到这个,因为有趣的人可以在HTTPGET 请求中向你发送完整的URL,Apache会将其传递给你。现在假设有人不小心为你的一个网页创建了一个看起来像'example.org//your/page/…
>>> urllib.parse.urlparse("//your/page/url")
ParseResult(scheme='', netloc='your', path='/page/url', params='', query='', fragment='')
这里的问题是,'//ahost.org/some/path'是一个完全合法的协议相关的 URL,所以这就是 urllib.parse 在你给它一个看起来像 URL 的东西时将产生的结果,也就是以'//'开头的东西。因为我们知道它是从哪里来的,你和我都知道这是一个前面有一个额外的 / 的相对 URL,但是urlparse()不能做这个假设,也没有办法限制它符合标准的通用性。
如果这对你来说是个问题(就像我最近遇到的那样),你能做的最好的事情就是在你调用 urlparse()之前检查前面的'//',然后把它变成'/'(简单的方法是把字符串中的第一个字符去掉)。做任何更复杂的事情都感觉太接近于试图真正理解 URL,这正是我们想要委托给 urlparse() 的工作,因为它很复杂。
PS: 因为我刚刚测试过,给 urlparse() 一个以三个或更多斜杠开头的相对 URL 的结果是,它被解释为一个相对 URL,而不是一个协议相对 URL。结果的path ,会有额外的前导斜杠被剥去。