规范化/规范化URL?

时间:2012-05-14 14:02:14

标签: url python-3.x normalization

我正在搜索一个库函数来规范化Python中的URL,即删除路径中的“./”或“../”部分,或添加默认端口或转义特殊字符等。结果应该是一个字符串,对于指向同一网页的两个URL是唯一的。例如,http://google.comhttp://google.com:80/a/../将返回相同的结果。

我更喜欢Python 3并且已经查看了urllib模块。它提供了分割URL的功能,但没有规范它们的功能。 Java有URI.normalize()函数做类似的事情(虽然它不认为默认端口80等于没有给定的端口),但有这样的东西是python吗?

6 个答案:

答案 0 :(得分:4)

这个怎么样:

In [1]: from urllib.parse import urljoin

In [2]: urljoin('http://example.com/a/b/c/../', '.')
Out[2]: 'http://example.com/a/b/'

灵感来自this question的答案。它没有规范化端口,但是它应该很简单地启动一个函数。

答案 1 :(得分:4)

这是我使用的,到目前为止它已经奏效了。你可以从pip获得urlnorm。

请注意,我对查询参数进行了排序。我发现这是必不可少的。

from urlparse import urlsplit, urlunsplit, parse_qsl
from urllib import urlencode
import urlnorm

def canonizeurl(url):
    split = urlsplit(urlnorm.norm(url))
    path = split[2].split(' ')[0]

    while path.startswith('/..'):
        path = path[3:]

    while path.endswith('%20'):
        path = path[:-3]

    qs = urlencode(sorted(parse_qsl(split.query)))
    return urlunsplit((split.scheme, split.netloc, path, qs, ''))

答案 2 :(得分:2)

urltools模块规范化多个斜杠,...组件,而不会弄乱http://中的双斜杠。

执行pip install urltools后,用法如下:

print urltools.normalize('http://domain.com:80/a////b/../c')
>>> 'http://domain.com/a/c'

答案 3 :(得分:1)

现在有一个专门解决此确切问题的图书馆url-normalize

它不仅可以按照文档对路径进行标准化:

URI规范化功能:

  1. 注意IDN域。
  2. 始终以小写字符提供URI方案。
  3. 始终以小写字符提供主机名。
  4. 仅在必不可少的地方执行百分比编码。
  5. 百分比编码时始终使用大写的A至F字符。
  6. 防止点段出现在非相对URI路径中。
  7. 对于定义默认权限的方案,如果需要默认权限,请使用空权限。
  8. 对于将空路径定义为等同于路径“ /”的方案,请使用“ /”。
  9. 对于定义端口的方案,如果需要默认端口,请使用空端口
  10. URI的所有部分都必须是来自Unicode字符串的utf-8编码的NFC

这里是一个例子:

from url_normalize import url_normalize

url = 'http://google.com:80/a/../'
print(url_normalize(url))

哪个给:

http://google.com/

答案 4 :(得分:0)

good start之后,我编写了一个方法,该方法适用于网络中常见的大多数情况。

def urlnorm(base, link=''):
  '''Normalizes an URL or a link relative to a base url. URLs that point to the same resource will return the same string.'''
  new = urlparse(urljoin(base, url).lower())
  return urlunsplit((
    new.scheme,
    (new.port == None) and (new.hostname + ":80") or new.netloc,
    new.path,
    new.query,
    ''))

答案 5 :(得分:0)

我在上面使用了@Antony的答案,并使用了url-normalize库,但是它有一个当前未修复的错误:当发送不带方案的URL时,偶然将其设置为HTTPS。我写了一个函数,通过将其设置为HTTP来包装和修复它:

from url_normalize import url_normalize
from urllib.parse import urlparse


def parse_url(url):
    return_val = url_normalize(url)
    wrong_default_prefix = "https://"
    new_default_prefix = "http://"
    # If the URL came with no scheme and the normalize function mistakenly 
    # set it to the HTTPS protocol, then fix it and set it to HTTP
    if urlparse(url).scheme.strip() == '' and return_val.startswith(wrong_default_prefix):
        return_val = new_default_prefix + return_val[len(wrong_default_prefix):]
    return return_val