【问题标题】:Python: Get URL path sectionsPython:获取 URL 路径部分
【发布时间】:2011-12-15 05:09:26
【问题描述】:

如何从 url 获取特定的路径部分?例如,我想要一个对此进行操作的函数:

http://www.mydomain.com/hithere?image=2934

并返回“这里”

或对此进行操作:

http://www.mydomain.com/hithere/something/else

并返回相同的东西(“hithere”)

我知道这可能会使用 urllib 或 urllib2,但我无法从文档中弄清楚如何只获取路径的一部分。

【问题讨论】:

  • URL 语法类似于:scheme://domain:port/path?query_string#fragment_id,所以“hithere”在第一种情况下是整个path,在第二种情况下是它的一部分。只需 urlparse 它然后 'hithere' 将是 path.split('/')[1]
  • 不会是path.split('/')[0]吗? (列表的第一项)
  • 否,因为路径以 '/' 开头,所以 [0] 是一个空字符串。 IE。 ideone.com/hJRxk

标签: python url


【解决方案1】:

urlparse提取URL的路径部分:

>>> import urlparse
>>> path = urlparse.urlparse('http://www.example.com/hithere/something/else').path
>>> path
'/hithere/something/else'

使用os.path.split将路径拆分成组件:

>>> import os.path
>>> os.path.split(path)
('/hithere/something', 'else')

dirname 和 basename 函数为您提供了拆分的两个部分;也许在 while 循环中使用 dirname:

>>> while os.path.dirname(path) != '/':
...     path = os.path.dirname(path)
... 
>>> path
'/hithere'

【讨论】:

  • 难道 urllib 没有任何功能可以做到这一点,而无需进行一堆字符串解析/拆分/循环?我以为会有捷径...
  • 不要将 os.path.split 用于 url,因为它依赖于平台。该代码将在 Windows 上失败,因为它需要 \ 作为分隔符!
  • @Viorel 这是不正确的。我刚测试过。使用os.path.join 是错误的,因为它会使用错误的分隔符,但split 方法仍然可以在/ 上拆分。实际上,您可以使用/ 作为 Python 中的目录分隔符来键入 Windows 的所有目录路径。使用 / 作为目录分隔符在 Windows 上的很多地方都可以使用,而不仅仅是在 Python 中。
  • os.path.split 可能会起作用,但我认为在这里使用它是不好的做法,因为它显然是用于 os 路径而不是 url 路径。
  • 对于 Windows 上包含 \ 的 URL,使用 os.path 将失败。请改用posixpath - 请参阅我的答案。
【解决方案2】:

Python 3.4+ 解决方案:

from urllib.parse import unquote, urlparse
from pathlib import PurePosixPath

url = 'http://www.example.com/hithere/something/else'

PurePosixPath(
    unquote(
        urlparse(
            url
        ).path
    )
).parts[1]

# returns 'hithere' (the same for the URL with parameters)

# parts holds ('/', 'hithere', 'something', 'else')
#               0    1          2            3

【讨论】:

    【解决方案3】:

    在处理 URL 的路径组件时,最好的选择是使用 posixpath 模块。此模块与os.path 具有相同的接口,并且在基于 POSIX 和 Windows NT 的平台上使用时始终在 POSIX 路径上运行。


    示例代码:

    #!/usr/bin/env python3
    
    import urllib.parse
    import sys
    import posixpath
    import ntpath
    import json
    
    def path_parse( path_string, *, normalize = True, module = posixpath ):
        result = []
        if normalize:
            tmp = module.normpath( path_string )
        else:
            tmp = path_string
        while tmp != "/":
            ( tmp, item ) = module.split( tmp )
            result.insert( 0, item )
        return result
    
    def dump_array( array ):
        string = "[ "
        for index, item in enumerate( array ):
            if index > 0:
                string += ", "
            string += "\"{}\"".format( item )
        string += " ]"
        return string
    
    def test_url( url, *, normalize = True, module = posixpath ):
        url_parsed = urllib.parse.urlparse( url )
        path_parsed = path_parse( urllib.parse.unquote( url_parsed.path ),
            normalize=normalize, module=module )
        sys.stdout.write( "{}\n  --[n={},m={}]-->\n    {}\n".format( 
            url, normalize, module.__name__, dump_array( path_parsed ) ) )
    
    test_url( "http://eg.com/hithere/something/else" )
    test_url( "http://eg.com/hithere/something/else/" )
    test_url( "http://eg.com/hithere/something/else/", normalize = False )
    test_url( "http://eg.com/hithere/../else" )
    test_url( "http://eg.com/hithere/../else", normalize = False )
    test_url( "http://eg.com/hithere/../../else" )
    test_url( "http://eg.com/hithere/../../else", normalize = False )
    test_url( "http://eg.com/hithere/something/./else" )
    test_url( "http://eg.com/hithere/something/./else", normalize = False )
    test_url( "http://eg.com/hithere/something/./else/./" )
    test_url( "http://eg.com/hithere/something/./else/./", normalize = False )
    
    test_url( "http://eg.com/see%5C/if%5C/this%5C/works", normalize = False )
    test_url( "http://eg.com/see%5C/if%5C/this%5C/works", normalize = False,
        module = ntpath )
    

    代码输出:

    http://eg.com/hithere/something/else
      --[n=True,m=posixpath]-->
        [ "hithere", "something", "else" ]
    http://eg.com/hithere/something/else/
      --[n=True,m=posixpath]-->
        [ "hithere", "something", "else" ]
    http://eg.com/hithere/something/else/
      --[n=False,m=posixpath]-->
        [ "hithere", "something", "else", "" ]
    http://eg.com/hithere/../else
      --[n=True,m=posixpath]-->
        [ "else" ]
    http://eg.com/hithere/../else
      --[n=False,m=posixpath]-->
        [ "hithere", "..", "else" ]
    http://eg.com/hithere/../../else
      --[n=True,m=posixpath]-->
        [ "else" ]
    http://eg.com/hithere/../../else
      --[n=False,m=posixpath]-->
        [ "hithere", "..", "..", "else" ]
    http://eg.com/hithere/something/./else
      --[n=True,m=posixpath]-->
        [ "hithere", "something", "else" ]
    http://eg.com/hithere/something/./else
      --[n=False,m=posixpath]-->
        [ "hithere", "something", ".", "else" ]
    http://eg.com/hithere/something/./else/./
      --[n=True,m=posixpath]-->
        [ "hithere", "something", "else" ]
    http://eg.com/hithere/something/./else/./
      --[n=False,m=posixpath]-->
        [ "hithere", "something", ".", "else", ".", "" ]
    http://eg.com/see%5C/if%5C/this%5C/works
      --[n=False,m=posixpath]-->
        [ "see\", "if\", "this\", "works" ]
    http://eg.com/see%5C/if%5C/this%5C/works
      --[n=False,m=ntpath]-->
        [ "see", "if", "this", "works" ]
    

    注意事项:

    • 在基于 Windows NT 的平台上,os.pathntpath
    • 在基于 Unix/Posix 的平台上,os.pathposixpath
    • ntpath 无法正确处理反斜杠 (\)(请参阅代码/输出中的最后两种情况)——这就是为什么推荐使用 posixpath
    • 记得用urllib.parse.unquote
    • 考虑使用posixpath.normpath
    • RFC 3986 未定义多个路径分隔符 (/) 的语义。但是,posixpath 折叠了多个相邻的路径分隔符(即它对待 ////// 相同)
    • 尽管 POSIX 和 URL 路径具有相似的语法和语义,但它们并不完全相同。

    规范性参考:

    【讨论】:

    • Python 3.4+ 解决方案:url_path = PurePosixPath(urllib.parse.unquote(urllib.parse.urlparse(url‌​).path)).
    • @Navin 值得将其发布为答案
    • 很好的答案。但是,如果其中一个废弃的 url 中有错误,则会失败。例如:test_url( "http://eg.com/hithere//something/else" ) 将导致while tmp != "/": 上的无限循环
    【解决方案4】:

    Python3 导入中的注释已更改为 from urllib.parse import urlparse 请参阅 documentation。这是一个例子:

    >>> from urllib.parse import urlparse
    >>> url = 's3://bucket.test/my/file/directory'
    >>> p = urlparse(url)
    >>> p
    ParseResult(scheme='s3', netloc='bucket.test', path='/my/file/directory', params='', query='', fragment='')
    >>> p.scheme
    's3'
    >>> p.netloc
    'bucket.test'
    >>> p.path
    '/my/file/directory'
    

    【讨论】:

      【解决方案5】:
      import urlparse
      
      output = urlparse.urlparse('http://www.example.com/temp/something/happen/index.html').path
      
      output
      
      '/temp/something/happen/index.html'
      
      Split the path -- inbuilt rpartition func of string 
      
      output.rpartition('/')[0]
      
      '/temp/something/happen'
      

      【讨论】:

        【解决方案6】:

        这是一个使用 urlparse 和 rpartition 的示例。

        # Python 2x:
        from urlparse import urlparse
        # Python 3x:
        from urllib.parse import urlparse
        
        def printPathTokens(full_url):
            print('printPathTokens() called: %s' % full_url)
        
            p_full = urlparse(full_url).path
        
            print(' . p_full url: %s' % p_full)
        
            # Split the path using rpartition method of string
            # rpartition "returns a tuple containing the part the before separator,
            # argument string and the part after the separator" 
            (rp_left, rp_match, rp_right) = p_full.rpartition('/')
        
            if rp_match == '': # returns the rpartition separator if found
                print(' . No slashes found in path')
            else:
                print(' . path to last resource: %s' % rp_left)
                if rp_right == '': # Ended with a slash
                    print(' . last resource: (none)')
                else:
                    print(' . last resource: %s' % (rp_right))
        
        
        printPathTokens('http://www.example.com/temp/something/happen/index.html')
        # Output:
        # printPathTokens() called: http://www.example.com/temp/something/happen/index.html
        # . p_full url: /temp/something/happen/index.html
        # . path to last resource: /temp/something/happen
        # . last resource: index.html
        
        printPathTokens('http://www.example.com/temp/something/happen/')
        # Output:
        # printPathTokens() called: http://www.example.com/temp/something/happen/
        # . p_full url: /temp/something/happen/
        # . path to last resource: /temp/something/happen
        # . last resource: (none)
        
        printPathTokens('http://www.example.com/temp/something/happen')
        # Output:
        # printPathTokens() called: http://www.example.com/temp/something/happen
        # . p_full url: /temp/something/happen
        # . path to last resource: /temp/something
        # . last resource: happen
        

        【讨论】:

          【解决方案7】:

          urlparseos.path.split 的组合可以解决问题。以下脚本将 url 的所有部分向后存储在一个列表中。

          import os.path, urlparse
          
          def generate_sections_of_url(url):
              path = urlparse.urlparse(url).path
              sections = []; temp = "";
              while path != '/':
                  temp = os.path.split(path)
                  path = temp[0]
                  sections.append(temp[1])
              return sections
          

          这将返回:["else", "something", "hithere"]

          【讨论】:

            【解决方案8】:
            from urllib.parse import urlparse
            
            o = urlparse('http://www.example.com/p1/p2/p3').path
            
            print(o)
            

            输出:

            /p1/p2/p3
            

            完成。

            【讨论】:

            • 这在其他答案中已经提到了。
            猜你喜欢
            • 2011-10-20
            • 2017-10-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-28
            • 1970-01-01
            • 2011-05-28
            相关资源
            最近更新 更多