【问题标题】:Canonical URL compare in Python?Python中的规范URL比较?
【发布时间】:2010-07-19 21:36:09
【问题描述】:

是否有任何工具可以在 Python 中进行 URL 比较?

例如,如果我有 http://google.comgoogle.com/,我想知道它们很可能是同一个站点。

如果我要手动构建规则,我可能会将其大写,然后去掉http:// 部分,并在最后一个字母数字字符之后删除任何内容。但我可以看到这个失败,因为我是当然你也可以。

有没有这样的图书馆?你会怎么做?

【问题讨论】:

  • 它不会让您发布两个没有 X 信誉的 链接,但是如果您将它们放在反引号中,那么您可以包含任意数量的 URL,以便解析器不会t 将它们转换为链接。我编辑了您的问题以表明我认为您的意思,但如果我弄错了,请再次编辑以纠正我。
  • 哦,还有一件事:“模糊”比较到底是什么意思?很容易看出 http://google.comgoogle.com/ 是同一件事,因为它们具有完全相同的规范形式,但这不是模糊比较。真正的模糊比较会识别出相似但不相同的 URL,即使您将它们转换为标准形式也是如此。
  • 谢谢,对 SO 还是很陌生。我改了标题。
  • intertwingly.net/stories/2004/08/04/urlnorm.py 似乎是一个不错的起点。

标签: python fuzzy-comparison


【解决方案1】:

这在我脑海中浮现:

def canonical_url(u):
    u = u.lower()
    if u.startswith("http://"):
        u = u[7:]
    if u.startswith("www."):
        u = u[4:]
    if u.endswith("/"):
        u = u[:-1]
    return u

def same_urls(u1, u2):
    return canonical_url(u1) == canonical_url(u2)

显然,还有很多空间可以摆弄这个。正则表达式可能比开头和结尾更好,但你明白了。

【讨论】:

  • 这类似于我要手动构建的内容。我希望有一个已经这样做的库。看来这应该是一个已解决的问题。
  • @Colin:这是其中自己做的事情通常很容易,而且更有可能得到你真正想要的东西。问题是 URL 没有严格定义的“规范形式”,所以每个想要它的人都在想一些稍微不同的东西。
  • 我同意 Nicholas 的观点:这定义不够明确,无法获得标准定义。最好自己写。
  • 小写整个 URL 让我觉得这是个坏主意 - URL 中大小写确实很重要(除了主机和域)
【解决方案2】:

您可以使用 dns 查找名称,看看它们是否指向相同的 ip。可能需要一些较小的字符串处理来删除混淆字符。

from socket import gethostbyname_ex

urls = ['http://google.com','google.com/','www.google.com/','news.google.com']

data = []
for orginalName in urls:
    print 'url:',orginalName
    name = orginalName.strip()
    name = name.replace( 'http://','')
    name = name.replace( 'http:','')
    if name.find('/') > 0:
        name = name[:name.find('/')]
    if name.find('\\') > 0:
        name = name[:name.find('\\')]
    print 'dns lookup:', name
    if name:
        try:
            result = gethostbyname_ex(name)
        except:
            continue # Unable to resolve
        for ip in result[2]:
            print 'ip:', ip
            data.append( (ip, orginalName) )

print data

结果:

url: http://google.com
dns lookup: google.com
ip: 66.102.11.104
url: google.com/
dns lookup: google.com
ip: 66.102.11.104
url: www.google.com/
dns lookup: www.google.com
ip: 66.102.11.104
url: news.google.com
dns lookup: news.google.com
ip: 66.102.11.104
[('66.102.11.104', 'http://google.com'), ('66.102.11.104', 'google.com/'), ('66.102.11.104', 'www.google.com/'), ('66.102.11.104', 'news.google.com')]

【讨论】:

    【解决方案3】:

    显然有quite a bit to creating a canonical urlurl-normalize 库是我测试过的最好的库。

    根据您的网址来源,您可能希望清除其他标准参数,例如UTM codesw3lib.url.url_query_cleaner 对此很有用。

    将此与Ned Batchelder's answer 结合起来可能类似于:

    代码:

    from w3lib.url import url_query_cleaner
    from url_normalize import url_normalize
    
    urls = ['google.com',
    'google.com/',
    'http://google.com/',
    'http://google.com',
    'http://google.com?',
    'http://google.com/?',
    'http://google.com//',
    'http://google.com?utm_source=Google']
    
    
    def canonical_url(u):
        u = url_normalize(u)
        u = url_query_cleaner(u,parameterlist = ['utm_source','utm_medium','utm_campaign','utm_term','utm_content'],remove=True)
    
        if u.startswith("http://"):
            u = u[7:]
        if u.startswith("https://"):
            u = u[8:]
        if u.startswith("www."):
            u = u[4:]
        if u.endswith("/"):
            u = u[:-1]
        return u
    
    list(map(canonical_url,urls))
    

    结果:

    ['google.com',
     'google.com',
     'google.com',
     'google.com',
     'google.com',
     'google.com',
     'google.com',
     'google.com']
    

    【讨论】:

      【解决方案4】:

      它不是“模糊”,它只是找到两个字符串之间的“距离”:

      http://pypi.python.org/pypi/python-Levenshtein/

      我会删除所有对 URL 解析具有语义意义的部分(协议、斜杠等),标准化为小写,然后执行 levenstein 距离,然后从那里决定有多少差异是可接受的阈值。

      只是一个想法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-07-14
        • 2011-07-11
        • 2020-11-23
        • 2011-07-19
        • 2010-09-12
        • 1970-01-01
        • 2012-05-22
        相关资源
        最近更新 更多