74

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

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

我需要一个 python 库,它将额外的空间(或任何其他非规范化字符)转换为正确的 URL。

4

8 回答 8

74

看看这个模块: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))
于 2008-09-23T13:33:06.940 回答
58

Python 2.7 中针对该问题的真正修复

正确的解决方案是:

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

有关更多信息,请参阅Issue918368:“urllib 不正确服务器返回的 url”

于 2009-05-10T16:15:40.697 回答
24

使用urllib.quoteurllib.quote_plus

urllib 文档

报价(字符串[,安全])

使用“%xx”转义替换字符串中的特殊字符。从不引用字母、数字和字符“_.-”。可选的安全参数指定不应被引用的附加字符——它的默认值为'/'。

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

报价加(字符串[,安全])

与 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 和 urlparse.urlunparse来解析 url 并且只对路径进行编码。这可能对您更有用,尽管如果您从已知协议和主机构建 URL 但路径可疑,您可能也可以避免 urlparse 并仅引用 URL 的可疑部分,并连接已知的安全部件。

于 2008-09-23T13:26:16.973 回答
13

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

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

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

于 2009-06-07T16:35:25.343 回答
10

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'

这仅引用路径组件。

于 2008-09-23T13:25:01.767 回答
4

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

于 2009-12-16T03:43:51.860 回答
2

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

于 2017-03-05T15:12:43.023 回答
1

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

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

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

于 2014-06-13T10:45:33.300 回答