Python:获取 URL 路径部分

Posted

技术标签:

【中文标题】Python:获取 URL 路径部分【英文标题】:Python: Get URL path sections 【发布时间】: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 【参考方案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 路径具有相似的语法和语义,但它们并不完全相同。

规范性参考:

IEEE Std 1003.1, 2013 - Vol. 1: Base Definitions - Section 4.12: Pathname Resolution The GNU C Library Reference Manual - Section 11.2: File Names IETF RFC 3986: Uniform Resource Identifier (URI): Generic Syntax - Section 3.3: Path IETF RFC 3986: Uniform Resource Identifier (URI): Generic Syntax - Section 6: Normalization and Comparison Wikipedia: URL normalization

【讨论】:

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】:

urlparse 和 os.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

完成。

【讨论】:

这在其他答案中已经提到了。

以上是关于Python:获取 URL 路径部分的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript - 获取 URL 路径的一部分

如何使用Cmake字符串正则表达式替换从路径url的多个实例中获取路径url的最后一部分并用它替换整个路径

如何在 Python 中只获取路径的最后一部分?

[javaSE] 网络编程(URL)

前端获得Url信息

使用长颈瓶在python中获取当前页面网址的一部分