提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
我正在使用urljoin来获取页面链接的绝对URL。 在大多数情况下,它在解决相对链接等方面都做得很好,但是我注意到,由于某些原因,它在某些情况下不能去除多余的点。 例如:
>>> urljoin("http://x.com","http://x.com/../../X",False)
'http://x.com/../../X'
>>> urljoin("http://x.com","http://x.com/./../X",False)
'http://x.com/./../X'
如果将这样的URL提供给Web浏览器,它将对其进行更正,但是,如果我尝试使用Python的urlopen(),则会引发异常(urllib2.HTTPError:HTTP错误400:错误请求)。
这是预期的行为吗? 是否有其他Python函数可以正确删除我应该使用的这些点,还是一个bug?
我认为您应该使用绝对base
和相对url
。
如果您这样称呼它,它将去除圆点:
urljoin("http://x.com/a/b/page.html","../../index.html",False)
# result: 'http://x.com/index.html'
urljoin("http://x.com/a/b/page.html","./index.html",False)
# result: 'http://x.com/a/b/index.html'
我在此答案中找到了标准化URL的方法。 例:
urljoin('http://www.example.com/foo/bar/../../baz/bux/', '.')
# result: 'http://www.example.com/baz/bux/'
我认为无效的url处理(太多..
)只能“手动”处理,如下所示:
def remove_extra_dots(url):
parsed = list(urlparse(url))
dirs = []
for name in parsed[2].split("/"):
if name == "..":
if len(dirs) > 1:
dirs.pop()
else:
dirs.append(name)
parsed[2] = "/".join(dirs)
return urlunparse(parsed)
这会从网址中删除所有..
,即使是无效的也是如此。 例子:
"http://x.com/a/b/c/../../X" #-> http://x.com/a/X
"http://x.com/a/b/../../X" #-> http://x.com/X
"http://x.com/../../X" #-> http://x.com/X
有点bug! 根据RFC 3986 ,应删除那些多余的..
段。 我没有能够找到的Python标准库函数确实可以正确地完成工作。
遗憾的是,现有的答案在某些方面有些不正确。 URL解析比预期的要复杂一些。
除了urljoin
提到的urljoin
的缺点(加入绝对路径时,它不能解析URL,也不能处理过多的..
s),而将URL与结合在一起.
将删除最后一段。 例如, urljoin('http://example.com/dir/./wrong/../file.txt', '.')
将导致'http://example.com/dir/'
,删除文件,因此您必须将其重新添加。此外, urljoin('http://example.com/dir/..', '.')
结果为'http://example.com/dir/'
,这只是您的情况的错误。
不仅如此,提供的remove_extra_dots
函数实际上存在一个错误。 如果URL以结尾的句点结尾(上一段中的最后一个bug使得它不可能,但是如果已通过某种方式解决了), 则不会添加结尾的斜杠。 考虑remove_extra_dots('http://example.com/..')
。 这应该是'http://example.com/'
,但实际上是'http://example.com'
(请注意缺少斜杠)。 差异不大,但是很多站点都会在收到丢失的斜杠时进行重定向,因此您可能会得到意想不到的结果。
以下功能可完全解析URL,即两个URL .
s和..
s-遵循RFC3986。也不必依赖urljoin
!
try:
# Python 3
from urllib.parse import urlsplit, urlunsplit
except ImportError:
# Python 2
from urlparse import urlsplit, urlunsplit
def resolve_url(url):
parts = list(urlsplit(url))
segments = parts[2].split('/')
segments = [segment + '/' for segment in segments[:-1]] + [segments[-1]]
resolved = []
for segment in segments:
if segment in ('../', '..'):
if resolved[1:]:
resolved.pop()
elif segment not in ('./', '.'):
resolved.append(segment)
parts[2] = ''.join(resolved)
return urlunsplit(parts)
当您拥有完整的URL(在您的情况下,加入后)时,可以按以下方式调用它。
>>> resolve_url("http://example.com/dir/../../thing/.")
'http://example.com/thing/'
有关有效/无效的更多信息,请参阅我在此主题上写的类似答案 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.