Python:如何解析包含';的URL';

Python:如何解析包含';的URL';,python,url,Python,Url,我需要唯一地标识和存储一些URL。问题是有时它们包含“.”如http://somedomain.com/foo/bar/../../some/url基本上是http://somedomain.com/some/url如果我没有错的话 是否有Python函数或棘手的方法来解析此URL?这些是文件路径。看看: 编辑: 如果在Windows上,则输入路径将使用反斜杠而不是斜杠。在这种情况下,您仍然需要os.path.normpath来摆脱。模式(以及/和/./以及任何其他多余的模式),然后将反斜杠转换

我需要唯一地标识和存储一些URL。问题是有时它们包含“.”如
http://somedomain.com/foo/bar/../../some/url
基本上是
http://somedomain.com/some/url
如果我没有错的话


是否有Python函数或棘手的方法来解析此URL?

这些是文件路径。看看:

编辑:

如果在Windows上,则输入路径将使用反斜杠而不是斜杠。在这种情况下,您仍然需要
os.path.normpath
来摆脱
模式(以及
/
/./
以及任何其他多余的模式),然后将反斜杠转换为正斜杠:

def fix_path_for_URL(path):
    result = os.path.normpath(path)
    if os.sep == '\\':
        result = result.replace('\\', '/')
    return result
编辑2:

如果要规范化URL,请使用模块进行规范化(在剥离方法等之前),如中所示

编辑3:

似乎
urljoin
没有规范化给定的基本路径:

>>> import urlparse
>>> urlparse.urljoin('http://somedomain.com/foo/bar/../../some/url', '')
'http://somedomain.com/foo/bar/../../some/url'
normpath
本身也不能完全切断它:

>>> import os
>>> os.path.normpath('http://somedomain.com/foo/bar/../../some/url')
'http:/somedomain.com/some/url'
注意,最初的双斜杠被吃掉了

因此,我们必须让他们联合起来:

def fix_URL(urlstring):
    parts = list(urlparse.urlparse(urlstring))
    parts[2] = os.path.normpath(parts[2].replace('/', os.sep)).replace(os.sep, '/')
    return urlparse.urlunparse(parts)
用法:

>>> fix_URL('http://somedomain.com/foo/bar/../../some/url')
'http://somedomain.com/some/url'

有一个简单的解决方案,使用:

但是,如果没有尾随斜杠(最后一个组件是文件,而不是目录),最后一个组件将被删除

此修复程序使用urlparse函数提取路径,然后使用(的posixpath版本)规范化组件。补偿,然后将URL重新连接在一起。以下是
doctest
able:

from urllib.parse import urlparse
import posixpath

def resolve_components(url):
    """
    >>> resolve_components('http://www.example.com/foo/bar/../../baz/bux/')
    'http://www.example.com/baz/bux/'
    >>> resolve_components('http://www.example.com/some/path/../file.ext')
    'http://www.example.com/some/file.ext'
    """
    parsed = urlparse(url)
    new_path = posixpath.normpath(parsed.path)
    if parsed.path.endswith('/'):
        # Compensate for issue1707768
        new_path += '/'
    cleaned = parsed._replace(path=new_path)
    return cleaned.geturl()

我想评论一下顶部响应中的
resolveComponents
函数

请注意,如果您的路径是
/
,则代码将添加另一个可能有问题的路径。 因此,我将
IF
条件更改为:

if parsed.path.endswith( '/' ) and parsed.path != '/':
根据这一点,这应该是“相对解决”过程的一部分。所以答案可能是
urlparse.urljoin(url,”)
。但由于错误,当第二个参数为空url时,urlparse.urljoin不会删除点段。您可以使用-alternative url操纵库。它正确地做到了这一点:

>>> import yurl
>>> print yurl.URL('http://somedomain.com/foo/bar/../../some/url') + yurl.URL()
http://somedomain.com/some/url

urljoin
不起作用,因为它只在第二个参数不是绝对(!?)或空时解析点段。不仅如此,它不会根据正确地处理过多的
s(它们应该被删除;
urljoin
不会这样做)
posixpath.normpath
也不能使用
(更不用说
os.path.normpath)
,因为它将一行中的多个斜杠解析为一个斜杠(例如
/////code>变成
///code>),这对于URL来说是不正确的行为


下面的短函数正确解析任何URL路径字符串。但是,它不应与相对路径一起使用,因为需要对其行为做出其他决定(在过多的
上引发错误)。
s?在开始时删除
?将两者都保留?)-相反,如果知道可以处理相对路径,请在解析之前连接URL。不言而喻:

def resolve_url_path(path):
    segments = path.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)
    return ''.join(resolved)
这将正确处理尾随点段(即,没有尾随斜杠)和连续斜杠。要解析整个URL,您可以使用以下包装器(或者只将路径解析函数内联到其中)


你可以这样称呼它:

>>> resolve_url('http://example.com/../thing///wrong/../multiple-slashes-yeah/.')
'http://example.com/thing///multiple-slashes-yeah/'
事实证明,正确的URL解析有很多陷阱

导入URL解析 导入posixpath parsed=list(urlparse.urlparse(url)) 已解析[2]=posixpath.normpath(posixpath.join(已解析[2],rel_path)) 正确的url=urlparse.urlparse(已解析)
URL。我把它们放在这里是因为我把它们放在了域名、方案等的后面……请看@jledev:这对我不起作用。“.”的数字可以不同,并且在URL中的不同位置。这甚至不起作用:urlparse.urljoin(“,“/…”)在我的机器上喊“.”|@Nicolae将其更改为
。/..
工作;我会纠正的。至少Firefox,而且,我想,所有体面的浏览器都不会发送这种风格的请求——他们会自己解释../的。就我个人而言,我会忽略这些URL或发送
400错误请求
。请注意,“在Windows上,它会将正向斜杠转换为反向斜杠。”这几乎是完美的,但可能我的问题不够具体(我已编辑以更恰当地反映这一点):这些是URL,我刚刚省略了域名和架构。这将路径
/foo/bar/./../some/url'
转换为python 3中mac上的
/some/url
。太棒了!效果很好。万分感谢!您也应该保留旧示例,并将其添加为编辑,因为这纯粹是一个了不起的例子,也许它会帮助其他可怜的灵魂幸运的是,如果URL中有太多
,这似乎不起作用。e、 g.
urljoin('http://x.com/../index.html“,”。)
->
'http://x.com/../“
而不是正确的
”http://x.com/index.html遗憾的是,如果第二个组件是绝对的,则'
urljoin
也不起作用。例如,
urljoin(“http://example.com/blah.html“,”//whoa.html“
会删除点,而
urljoin(”http://example.com/blah.html“,”/././//whoa.html“
不会。哦,还有,
posixpath.normpath
规范化了几个斜杠(例如
“///code>)根据RFC和浏览器的实现,这种情况不应该发生。“它不会正确地处理过多的
s”-在Python 3.5(但不是2.7)和3.4上都会发生:(你能详细解释一下为什么
//
变成
/
对URL来说是不正确的行为吗?我浏览了全文,找到了关键字
/
,但找不到任何他们认为路径中相邻的斜杠有意义的东西,例如
/
。@raylo看一看
def resolve_url_path(path):
    segments = path.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)
    return ''.join(resolved)
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))
    parts[2] = resolve_url_path(parts[2])
    return urlunsplit(parts)
>>> resolve_url('http://example.com/../thing///wrong/../multiple-slashes-yeah/.')
'http://example.com/thing///multiple-slashes-yeah/'