Разбор пользовательских URI с помощью urlparse (Python) - PullRequest
13 голосов
/ 13 сентября 2009

Мое приложение создает пользовательские URI (или URL?) Для идентификации объектов и их разрешения. Проблема в том, что модуль Python urlparse отказывается анализировать неизвестные схемы URL, как он анализирует http.

Если я не корректирую списки использования 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)

Почему нет лучшего способа сделать это?

Ответы [ 6 ]

23 голосов
/ 07 июня 2011

Вы также можете зарегистрировать пользовательский обработчик с помощью 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'}
3 голосов
/ 05 июня 2013

Существует также библиотека с именем 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'
3 голосов
/ 13 сентября 2009

Я думаю, что проблема в том, что URI не все имеют общий формат после схемы. Например, mailto: urls не имеет такой структуры, как http: urls.

Я бы использовал результаты первого разбора, затем синтезировал http-URL и снова его проанализировал:

parts = urlparse.urlparse("qqqq://base/id#hint")
fake_url = "http:" + parts[2]
parts2 = urlparse.urlparse(fake_url)
2 голосов
/ 20 января 2016

Вопрос устарел. По крайней мере, в 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')
1 голос
/ 05 февраля 2011

Попробуйте полностью удалить схему и начните с // 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='')
0 голосов
/ 25 декабря 2013

Вы можете использовать библиотеку 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')
...