【问题标题】:How can I normalize a URL in python如何在 python 中规范化 URL
【发布时间】:2010-09-12 08:47:38
【问题描述】:

我想知道我是否在 python 中规范化 URL。

例如,如果我有一个 url 字符串,例如:“http://www.example.com/foogoo/bar.html”

我需要一个 Python 库,它将多余的空格(或任何其他非规范化字符)转换为正确的 URL。

【问题讨论】:

标签: python url normalization normalize


【解决方案1】:

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'

这仅引用路径组件。

【讨论】:

  • 那只是引用所有字符。这对他没有帮助。
  • 在这个例子中,它也会引用 ':' 字符(不是全部)。感谢您的评论。
【解决方案2】:

看看这个模块: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 可能是更准确的解决方案,但我认为这是矫枉过正,还是我错过了什么?
  • 是的。你可能错过了这个问题。他有一个来自用户输入的 URL,并希望将其正确转换为真实的 URL。 (又名:做 Firefox 位置栏所做的事情)
  • url_fix 现在位于werkzeug.urls
  • @ArminRonacher 这个函数很棒但是不幸的是它没有执行完整的syntax-based normalization,即大小写规范化+百分比编码规范化+路径段规范化,也不是scheme-based normalization,正如RFC中定义的那样3986. 你知道任何能够做到这一点的 Python 库(标准或非标准)吗?我不敢相信 Python 没有这样一个基本的标准特性。
【解决方案3】:

适用于 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

【讨论】:

    【解决方案4】:

    我遇到这样一个问题:只需要引用空格。

    fullurl = quote(fullurl, safe="%/:=&?~#+!$,;'@()*[]") 帮忙,但是太复杂了。

    所以我使用了一个简单的方法:url = url.replace(' ', '%20'),它并不完美,但它是最简单的方法,并且适用于这种情况。

    【讨论】:

      【解决方案5】:

      仅供参考,urlnorm 已移至 github: http://gist.github.com/246089

      【讨论】:

        【解决方案6】:

        因为此页面是 Google 搜索该主题的最佳结果,所以我认为值得一提的是使用 Python 进行的 URL 规范化方面的一些工作,这些工作超出了对空格字符进行 urlencoding 的处理。例如,处理默认端口、字符大小写、缺少尾部斜杠等。

        在开发 Atom 联合格式时,有一些关于如何将 URL 标准化为规范格式的讨论;这记录在 Atom/Pie wiki 上的文章 PaceCanonicalIds 中。那篇文章提供了一些很好的测试用例。

        我相信这次讨论的一个结果是 Mark Nottingham 的 urlnorm.py 库,我在几个项目中使用它并取得了不错的效果。但是,该脚本不适用于此问题中给出的 URL。因此,更好的选择可能是 Sam Ruby's version of urlnorm.py,它处理该 URL,以及来自 Atom wiki 的所有上述测试用例。

        【讨论】:

          【解决方案7】:

          Real fix in Python 2.7 for that problem

          正确的解决方案是:

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

          欲了解更多信息,请参阅Issue918368: "urllib doesn't correct server returned urls"

          【讨论】:

          • 优秀的答案,简洁且乐于助人。由于此更改在 urllib 内部,因此希望执行相同操作的代码应 import urllib 并使用上述参数调用 urllib.quote()
          • 这对字母 ä 表示反对,但我给它投票,因为它很简单,并且不需要再次导入。
          【解决方案8】:

          使用urllib.quoteurllib.quote_plus

          来自urllib documentation

          quote(string[, safe])

          替换字符串中的特殊字符 使用“%xx”转义。信件, 数字,字符“_.-”是 从未引用过。可选的保险箱 参数指定附加 不应引用的字符 -- 默认值为'/'。

          示例:quote('/~connolly/') 产生 '/%7econnolly/'

          quote_plus(string[, safe])

          类似于quote(),但也替换空格 加号,根据引用要求 HTML 表单值。加号在 原始字符串被转义,除非 它们包含在安全中。它也是 没有安全的默认值'/'。

          编辑:在整个 URL 上使用 urllib.quote 或 urllib.quote_plus 会破坏它,正如@ΤZΩΤZΙΟΥ 指出的那样:

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

          @ΤZΩΤZΙΟΥ 提供了一个函数,它使用urlparse.urlparse and urlparse.urlunparse 来解析 url 并且只对路径进行编码。这可能对您更有用,尽管如果您从已知协议和主机构建 URL 但路径可疑,您可能也可以避免 urlparse 并仅引用 URL 的可疑部分,并连接已知的安全部件。

          【讨论】:

          • 那么,给定问题的示例 url,urllib.quote 返回什么?
          • 垃圾。为什么一个明显错误的答案被接受为解决方案?
          • @ΤZΩΤZΙΟΥ:好点。解决@Armin Ronacher:可能是因为回答者和接受者没有意识到问题 - 并非所有问题对所有人都是显而易见的。
          • 建议编辑:“……只编码主机名”→“……只引用路径”
          • 当然,@ΤZΩΤZΙΟΥ。谢谢!有时我不知道自己的大脑在哪里。
          猜你喜欢
          • 2013-07-14
          • 1970-01-01
          • 2012-05-22
          • 2011-05-09
          • 2011-02-28
          • 1970-01-01
          • 1970-01-01
          • 2018-07-24
          相关资源
          最近更新 更多