使用URLPRASE(Python)解析自定义URI

使用URLPRASE(Python)解析自定义URI,python,url,python-2.6,urlparse,Python,Url,Python 2.6,Urlparse,我的应用程序创建自定义URI(或URL?)来标识对象并解析它们。问题在于Python的urlparse模块拒绝像解析http一样解析未知的URL方案 如果我不调整urlparse的使用列表,我会得到以下结果: >>> urlparse.urlparse("qqqq://base/id#hint") ('qqqq', '', '//base/id#hint', '', '', '') >>> urlparse.urlparse("http://base/id#h

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

如果我不调整urlparse的使用列表,我会得到以下结果:

>>> 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)

为什么没有更好的方法来实现这一点呢?

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

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

parts = urlparse.urlparse("qqqq://base/id#hint")
fake_url = "http:" + parts[2]
parts2 = urlparse.urlparse(fake_url)

尝试完全删除方案,并从//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(除了片段):


您还可以向URLPASSE注册自定义处理程序:

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'}

还有一个名为的库,它提供您想要的结果:

>>>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'
你可以使用图书馆。与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')

这个问题似乎过时了。因为至少Python2.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')

我喜欢我自己的解决方法;我将不得不在我的自定义URL模块中一直进行这种往返。公平地说:我不喜欢依赖模块的内部结构,但我可以有所不同!urlparse还接受另一个参数,我不认为它没有任何区别。(示例:
urlparse.urlparse()qqqq://base/id#hint“,“http”)
我相信这个问题(或者它的答案,取决于您如何看待它)。但查询仍然没有正确解析…无论如何,谢谢。使用dir(urlparse)查找5个变量似乎是间接的/脆弱的(如果urlparse在新版本中发生更改,而不是公开这些内部内容怎么办?)。谢谢你的列表。想进一步支持这一点,从2016年4月26日开始;还分析了上面显示的基本内容:
wird_scheme=qqq://username:password@example.com/some/path?params=key#frag_ment'
。然后解析并显示用户名:
urlparse(奇怪的方案)。用户名#'username'
或显示查询:
urlparse(奇怪的方案).query)#“params=key”
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')