Разбор пользовательских URI с urlparse (Python)
Мое приложение создает пользовательские URI (или URL?) для идентификации объектов и их устранения. Проблема в том, что модуль urlparse Python отказывается разбирать неизвестные схемы URL-адресов, например, анализирует http.
Если я не настрою списки 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)
Почему нет лучшего способа сделать это?
Ответы
Ответ 1
Я думаю, проблема в том, что URI не все имеют общий формат после схемы. Например, mailto: URL-адреса не структурированы так же, как http: urls.
Я бы использовал результаты первого синтаксического анализа, затем синтезировал URL-адрес http и снова проанализировал его:
parts = urlparse.urlparse("qqqq://base/id#hint")
fake_url = "http:" + parts[2]
parts2 = urlparse.urlparse(fake_url)
Ответ 2
Вы также можете зарегистрировать собственный обработчик с помощью 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-like и будет правильно возвращать путь, фрагмент, имя пользователя/пароль и т.д.
urlparse.urlparse('moose://username:[email protected]:port/path?query=value#fragment')._asdict()
=> {'fragment': 'fragment', 'netloc': 'username:[email protected]:port', 'params': '', 'query': 'query=value', 'path': '/path', 'scheme': 'moose'}
Ответ 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'
Ответ 4
Вопрос выглядит устаревшим. Поскольку по крайней мере 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')
Ответ 5
Попробуйте полностью удалить схему и начните с //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='')
Ответ 6
Вы можете использовать yurl библиотеку. В отличие от пурпура или меха, он не пытается исправить ошибки urlparse. Он совместим с реализацией RFC 3986.
>>> import yurl
>>> yurl.URL('qqqq://base/id#hint')
URLBase(scheme='qqqq', userinfo=u'', host='base', port='', path='/id', query='', fragment='hint')