Как я могу нормализовать URL-адрес в Python

Я хотел бы знать, нормализую ли я URL-адрес в python.

Например, если у меня есть строка URL-адреса вида: «http://www.example.com/foo goo / bar.html»

Мне нужна библиотека на Python, которая преобразует дополнительное пространство (или любой другой ненормализованный символ) в правильный URL-адрес.

Здесь есть более свежий ответ на StackOverflow: stackoverflow.com/questions/10584861/…

stuckintheshuck 09.04.2013 01:31

Не думаю, что так лучше ...

Aaron Hall 15.07.2014 00:59
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
73
2
65 471
8

Ответы 8

Py3

from urllib.parse import urlparse, urlunparse, quote
def myquote(url):
    parts = urlparse(url)
    return urlunparse(parts._replace(path=quote(parts.path)))

>>> myquote('https://www.example.com/~user/with space/index.html?a=1&b=2')
'https://www.example.com/~user/with%20space/index.html?a=1&b=2'

Py2

import urlparse, urllib
def myquote(url):
    parts = urlparse.urlparse(url)
    return urlparse.urlunparse(parts[:2] + (urllib.quote(parts[2]),) + parts[3:])

>>> myquote('https://www.example.com/~user/with space/index.html?a=1&b=2')
'https://www.example.com/%7Euser/with%20space/index.html?a=1&b=2'

Это цитирует только компонент пути.

Вот просто цитирую всех персонажей. Это ему не поможет.

Armin Ronacher 23.09.2008 17:33

В этом примере он также будет заключать в кавычки символ «:» (не все). Спасибо за комментарий.

tzot 23.09.2008 17:49

используйте urllib.quote или urllib.quote_plus

Из документация urllib:

quote(string[, safe])

Replace special characters in string using the "%xx" escape. Letters, digits, and the characters "_.-" are never quoted. The optional safe parameter specifies additional characters that should not be quoted -- its default value is '/'.

Example: quote('/~connolly/') yields '/%7econnolly/'.

quote_plus(string[, safe])

Like quote(), but also replaces spaces by plus signs, as required for quoting HTML form values. Plus signs in the original string are escaped unless they are included in safe. It also does not have safe default to '/'.

Обновлено: использование urllib.quote или urllib.quote_plus по всему URL-адресу приведет к его искажению, как указывает @ ΤΖΩΤΖΙΟΥ:

>>> quoted_url = urllib.quote('http://www.example.com/foo goo/bar.html')
>>> quoted_url
'http%3A//www.example.com/foo%20goo/bar.html'
>>> urllib2.urlopen(quoted_url)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\python25\lib\urllib2.py", line 124, in urlopen
    return _opener.open(url, data)
  File "c:\python25\lib\urllib2.py", line 373, in open
    protocol = req.get_type()
  File "c:\python25\lib\urllib2.py", line 244, in get_type
    raise ValueError, "unknown url type: %s" % self.__original
ValueError: unknown url type: http%3A//www.example.com/foo%20goo/bar.html

@ ΤΖΩΤΖΙΟΥ предоставляет функцию, которая использует urlparse.urlparse и urlparse.urlunparse для анализа URL-адреса и только кодирования пути. Это может быть более полезно для вас, хотя, если вы создаете URL-адрес из известного протокола и хоста, но с подозрительным путем, вы, вероятно, могли бы сделать то же самое, чтобы избежать разбора URL-адресов и просто процитировать подозрительную часть URL-адреса, объединяясь с известные безопасные части.

Итак, что возвращает urllib.quote с учетом URL-адреса примера вопроса?

tzot 23.09.2008 17:51

Мусор. Почему в качестве решения принимается заведомо неправильный ответ?

Armin Ronacher 23.09.2008 18:13

@ ΤΖΩΤΖΙΟΥ: отличный момент. Адресован @Armin Ronacher: возможно, потому, что отвечающий и принимающий не знали о проблеме - не все проблемы очевидны для всех.

Blair Conrad 23.09.2008 18:27

предложенное редактирование: «… и кодировать только имя хоста» → «… и только указывать путь»

tzot 23.09.2008 18:58

Конечно, @ ΤΖΩΤΖΙΟΥ. Спасибо! Иногда я не знаю, где оставить свой мозг.

Blair Conrad 24.09.2008 14:58

Здесь нет ответа, только комментарий.

bukzor 20.03.2012 23:44

Взгляните на этот модуль: werkzeug.utils. (теперь в werkzeug.urls)

Функция, которую вы ищете, называется url_fix и работает следующим образом:

>>> from werkzeug.urls import url_fix
>>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)')
'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29'

В Werkzeug это реализовано следующим образом:

import urllib
import urlparse

def url_fix(s, charset='utf-8'):
    """Sometimes you get an URL by a user that just isn't a real
    URL because it contains unsafe characters like ' ' and so on.  This
    function can fix some of the problems in a similar way browsers
    handle data entered by the user:

    >>> url_fix(u'http://de.wikipedia.org/wiki/Elf (Begriffsklärung)')
    'http://de.wikipedia.org/wiki/Elf%20%28Begriffskl%C3%A4rung%29'

    :param charset: The target charset for the URL if the url was
                    given as unicode string.
    """
    if isinstance(s, unicode):
        s = s.encode(charset, 'ignore')
    scheme, netloc, path, qs, anchor = urlparse.urlsplit(s)
    path = urllib.quote(path, '/%')
    qs = urllib.quote_plus(qs, ':&=')
    return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))

Хотя это от http rfc2616, вероятно, более точное решение, я думаю, что это излишне, или я что-то пропускаю?

Florian Bösch 23.09.2008 17:40

Да. Вы, наверное, упустили вопрос. У него есть URL-адрес, введенный пользователем, и он хочет правильно преобразовать его в реальный URL-адрес. (Также: делайте то, что делает адресная строка Firefox)

Armin Ronacher 23.09.2008 18:14

url_fix теперь находится по адресу werkzeug.urls

sebpiq 11.09.2012 17:53

@ArminRonacher Эта функция прекрасна, но, к сожалению, она не выполняет полностью нормализация на основе синтаксиса, то есть нормализацию случая + нормализацию процентного кодирования + нормализацию сегмента пути, ни схемная нормализация, как определено в RFC 3986. Знаете ли вы какую-либо библиотеку Python (стандартную или нет? ) что это умеет? Я не могу поверить, что в Python нет такой базовой стандартной функции.

Maggyero 28.08.2019 18:10

Настоящее исправление этой проблемы в Python 2.7

Правильное решение было:

 # percent encode url, fixing lame server errors for e.g, like space
 # within url paths.
 fullurl = quote(fullurl, safe = "%/:=&?~#+!$,;'@()*[]")

Для получения дополнительной информации см. Проблема 918368: «urllib не исправляет URL, возвращенные сервером».

Отличный ответ, краткий и полезный. Поскольку это изменение было внутри urllib, код, который хочет сделать то же самое, должен вызвать import urllib и вызвать urllib.quote() с указанными выше параметрами.

Quinn Taylor 13.01.2011 08:33

Это искажает букву ä, но я отдаю ей свой голос, потому что это просто и не требует еще одного импорта.

mlissner 11.02.2011 07:21

Поскольку эта страница является одним из лучших результатов поиска Google по этой теме, я думаю, стоит упомянуть некоторую работу, которая была проделана по нормализации URL-адресов с помощью Python, которая выходит за рамки символов пробела urlencoding. Например, работа с портами по умолчанию, регистром символов, отсутствием косой черты в конце и т. д.

Когда разрабатывался формат синдикации Atom, было некоторое обсуждение того, как нормализовать URL-адреса в канонический формат; это описано в статье PaceCanonicalIds на вики-странице Atom / Pie. В этой статье представлены несколько хороших тестовых примеров.

Я считаю, что одним из результатов этого обсуждения стала библиотека Марка Ноттингема urlnorm.py, которую я использовал с хорошими результатами в паре проектов. Однако этот сценарий не работает с URL-адресом, указанным в этом вопросе. Таким образом, лучшим выбором может быть Версия urlnorm.py Сэма Руби, который обрабатывает этот URL, и все вышеупомянутые тестовые примеры из вики Atom.

К вашему сведению, urlnorm переместился на github: http://gist.github.com/246089

Сталкиваюсь с такой проблемой: нужно цитировать только пробел.

fullurl = quote(fullurl, safe = "%/:=&?~#+!$,;'@()*[]") действительно помогает, но это слишком сложно.

Поэтому я использовал простой способ: url = url.replace(' ', '%20'), он не идеален, но это самый простой способ, и он работает в данной ситуации.

Действительно для Python 3.5:

import urllib.parse

urllib.parse.quote([your_url], "\./_-:")

пример:

import urllib.parse

print(urllib.parse.quote("http://www.example.com/foo goo/bar.html", "\./_-:"))

вывод будет http://www.example.com/foo%20goo/bar.html

Шрифт: https://docs.python.org/3.5/library/urllib.parse.html?highlight=quote#urllib.parse.quote

Другие вопросы по теме