13

我的应用程序创建自定义 URI(或 URL?)来识别对象并解析它们。问题是 Python 的 urlparse 模块拒绝像解析 http 那样解析未知的 URL 方案。

如果我不调整 urlparse 的 uses_* 列表,我会得到:

>>> urlparse.urlparse("qqqq://base/id#hint")
('qqqq', '', '//base/id#hint', '', '', '')
>>> urlparse.urlparse("http://base/id#hint")
('http', 'base', '/id', '', '', 'hint')

这就是我所做的,我想知道是否有更好的方法来做到这一点:

import urlparse

SCHEME = "qqqq"

# One would hope that there was a better way to do this
urlparse.uses_netloc.append(SCHEME)
urlparse.uses_fragment.append(SCHEME)

为什么没有更好的方法来做到这一点?

4

6 回答 6

22

您还可以使用 urlparse 注册自定义处理程序:

import urlparse

def register_scheme(scheme):
    for method in filter(lambda s: s.startswith('uses_'), dir(urlparse)):
        getattr(urlparse, method).append(scheme)

register_scheme('moose')

这会将您的 url 方案附加到列表中:

uses_fragment
uses_netloc
uses_params
uses_query
uses_relative

然后 uri 将被视为类似 http 并正确返回路径、片段、用户名/密码等。

urlparse.urlparse('moose://username:password@hostname:port/path?query=value#fragment')._asdict()
=> {'fragment': 'fragment', 'netloc': 'username:password@hostname:port', 'params': '', 'query': 'query=value', 'path': '/path', 'scheme': 'moose'}
于 2011-06-07T11:00:59.977 回答
3

我认为问题在于 URI 在方案之后并不都有共同的格式。例如,mailto: url 的结构与 http: url 不同。

我会使用第一次解析的结果,然后合成一个 http url 并再次解析:

parts = urlparse.urlparse("qqqq://base/id#hint")
fake_url = "http:" + parts[2]
parts2 = urlparse.urlparse(fake_url)
于 2009-09-13T15:15:42.597 回答
3

还有一个名为furl的库,它可以为您提供所需的结果:

>>>import furl
>>>f=furl.furl("qqqq://base/id#hint");
>>>f.scheme
'qqqq' 

>>> f.host
'base'  
>>> f.path
Path('/id')
>>>  f.path.segments
['id']
>>> f.fragment                                                                                                                                                                                                                                                                 
Fragment('hint')   
>>> f.fragmentstr                                                                                                                                                                                                                                                              
'hint'
于 2013-06-04T21:22:13.333 回答
2

这个问题似乎已经过时了。由于至少 Python 2.7 没有问题。

Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
>>> import urlparse
>>> urlparse.urlparse("qqqq://base/id#hint")
ParseResult(scheme='qqqq', netloc='base', path='/id', params='', query='', fragment='hint')
于 2016-01-20T14:33:49.647 回答
1

尝试完全删除该方案,并从 //netloc 开始,即:

>>> SCHEME="qqqq"
>>> url="qqqq://base/id#hint"[len(SCHEME)+1:]
>>> url
'//base/id#hint'
>>> urlparse.urlparse(url)
('', 'base', '/id', '', '', 'hint')

urlparse 结果中不会有该方案,但无论如何您都知道该方案。

另请注意,Python 2.6 似乎可以很好地处理这个 url(除了片段):

$ python2.6 -c 'import urlparse; print urlparse.urlparse("qqqq://base/id#hint")'
ParseResult(scheme='qqqq', netloc='base', path='/id#hint', params='', query='', fragment='')
于 2011-02-05T13:33:25.900 回答
0

您可以使用yurl库。与 purl 或 furl 不同,它不会尝试修复 urlparse 错误。它与 RFC 3986 实现兼容。

>>> import yurl
>>> yurl.URL('qqqq://base/id#hint')
URLBase(scheme='qqqq', userinfo=u'', host='base', port='', path='/id', query='', fragment='hint')
于 2013-12-25T15:35:22.957 回答