代码之家  ›  专栏  ›  技术社区  ›  JasonSmith

检测文本字符串中的(淘气的或漂亮的)URL或链接

  •  37
  • JasonSmith  · 技术社区  · 15 年前

    如何检测(使用正则表达式或启发式)一系列文本(如注释)中的网站链接?

    目的是防止垃圾邮件。HTML被剥离,所以我需要检测复制和粘贴的邀请。 对于垃圾邮件发送者来说,发布链接并不经济,因为大多数用户无法成功访问该页面。 . 我想要建议、参考资料或讨论最佳实践。

    一些目标:

    • 低垂的水果状形状良好的URL( http://some-fqdn/some/valid/path.ext )
    • 但没有 http:// 前缀(即有效的fqdn+有效的http路径)
    • 还有什么有趣的事吗

    当然,我正在阻止垃圾邮件,但同样的过程可以用来自动链接文本。

    思想

    我在想一些事情。

    • 内容是本地语言的散文,所以我可以在检测中触发快乐。
    • 我应该先去掉所有空格,以便 www .example.com “?普通用户是否知道自己删除空间,或者浏览器是否“做我想做的”并为您删除空间?
    • 也许多次通过是一个更好的策略,扫描包括:
      • 格式正确的URL
      • 所有非空白后跟“.”,后跟任何有效的TLD
      • 还有别的吗?

    相关问题

    我读过这些,现在它们在这里被记录下来了,所以如果你想的话,你可以在这些问题中引用正则表达式。

    更新和摘要

    哇,我这里列出了一些非常好的启发式方法!对我来说,赚钱最好的方法是综合以下几点:

    1. @乔恩·布赖特的TLD检测技术(一个很好的防御瓶颈)
    2. 对于那些可疑的字符串,请根据@capar用一个点型字符替换该点。
    3. 一个好的点型字符是@sharkey的subscripted·(即) · “”。·也是单词边界,因此很难随意复制和粘贴。

    这应该使垃圾邮件发送者的CPM足够低,以满足我的需要;用户的“标记为不适当”反馈应该捕获任何其他信息。列出的其他解决方案也非常有用:

    • 去掉所有有点的四边形(@sharkey对自己答案的评论)
    • @SporkMonger对客户端javascript的要求,它在表单中插入了一个必需的隐藏字段。
    • Ping URL服务器端以确定它是否为网站。(也许我可以通过spamasassin或另一个bayesian过滤器运行html,如@nathan..)
    • 查看Chrome智能地址栏的源代码,看看Google使用了什么巧妙的技巧
    • 呼叫OWASP反垃圾邮件或其他Web服务进行垃圾邮件/恶意软件检测。
    13 回复  |  直到 6 年前
        1
  •  19
  •   Jon Bright    15 年前

    我的答案集中在避免垃圾邮件发送者上。这导致了两个子假设:因此,使用系统的人将积极地试图违反您的检查,而您的目标只是检测是否存在URL,而不是提取完整的URL。如果你的目标是别的,这个解决方案看起来会有所不同。

    我认为你最好的选择是TLD。有两个字母CCTLD和(目前)其他比较小的列表。它们需要以一个点作为前缀,并由斜线或某些单词边界作为后缀。正如其他人所指出的,这并不完美。没有办法买到“BuyFunkyPharmaceuticals”。我又试了一次,说“不禁止合法的”。它不起作用”或类似的。所有这些都说,这是我的建议:

    [^\b]\.([a-zA-Z]{2}|aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel)[\b/]
    

    会得到的东西:

    当然,一旦人们开始混淆他们的网址,用“dot”替换“.”,它就会中断。但是,再次假设垃圾邮件发送者是你的目标,如果他们开始这样做,他们的点击率将下降另外两个数量级为零。我认为,这组人足够了解一个网址,而这组人不够了解,不足以访问垃圾邮件网站,有一个微小的交叉点。这个解决方案应该可以让您检测到所有可复制和粘贴到地址栏的URL,同时将附带的损坏降到最低。

        2
  •  13
  •   dentarg    8 年前
        3
  •  6
  •   Nathan    15 年前

    我不确定用regex检测URL是否是解决这个问题的正确方法。通常,你会错过一些模糊的边缘情况,垃圾邮件发送者将能够利用,如果他们有足够的动机。

    如果你的目标只是过滤掉评论中的垃圾邮件,那么你可能需要考虑 Bayesian 过滤。事实证明,它在将电子邮件标记为垃圾邮件时非常准确,它也可能为您做同样的事情,这取决于您需要过滤的文本量。

        4
  •  6
  •   Arnold Spence    15 年前

    我知道这对自动链接文本没有帮助,但是如果你搜索并用一个看起来相同的字符替换所有的句号,比如希伯来文点hiriq的unicode字符(u+05b4),会怎么样?

    以下段落为示例:

    这可能会奏效这段时间看起来有点奇怪,但它仍然可读当然,好处是任何人复制和粘贴www google com都不会走得太远com:。

        5
  •  4
  •   Benson    15 年前

    显然,低挂水果是从http://www.开始的,试图过滤掉“www”之类的东西。G邮件。“com”会引出一些有趣的哲学问题,比如你想走多远。你想在下一步过滤掉“www.dot gee mail.com”吗?关于URL的抽象描述,比如“万维网的缩写后面跟着一个点,后面跟着字母G,后面跟着单词mail,后面跟着一个点,最后是商业的TLD缩写”。

    在你继续设计你的算法之前,画一条你要过滤的东西的线是很重要的。我认为这条线应该画在“gmail.com”被认为是一个URL,但“gmail”的水平上。com不是。否则,每当有人不把句子中的第一个字母大写时,你很可能会得到误报。

        6
  •  3
  •   J c    15 年前

    由于您主要是在寻找复制和粘贴到浏览器地址栏的邀请,因此有必要查看开源浏览器(如Chrome或Mozilla)中使用的代码,以确定输入“地址栏等效项”的文本是搜索查询还是URL导航尝试。

        7
  •  2
  •   ramanujan    15 年前

    Ping可能的URL

    如果您不介意进行服务器端的计算,那么这样的事情怎么样?

    urls = []
    for possible_url in extracted_urls(comment):
        if pingable(possible_url):
           urls.append(url)  #you could do this as a list comprehension, but OP may not know python
    

    在这里:

    1. 提取的URL接受注释,并使用保守的regex提取可能的候选对象

    2. Pingable实际上使用系统调用来确定Web上是否存在主机名。您可以有一个简单的包装器来解析ping的输出。

      [ramanujan:~/base]$ping-c 1 www.google.com

      Ping www.l.google.com(74.125.19.147):56个数据字节 来自74.125.19.147的64个字节:icmp_seq=0 ttl=246 time=18.317 ms

      ——www.l.google.com ping统计--- 传输1个数据包,接收1个数据包,0%数据包丢失 往返最小/平均/最大/标准偏差=18.317/18.317/18.317/0.000 ms

      [ramanujan:~/base]$ping-c 1 fooalksdflajkd.com

      Ping:无法解析fooalksdflajkd.com: 未知主机

    缺点是,如果主机给出404,您将无法检测到它,但这是一个非常好的第一步——验证地址是否为网站的最终方法是尝试导航到它。您也可以尝试使用该URL,但这更为重要。

        8
  •  1
  •   Bob Aman    15 年前

    在多次尝试编写这段精确的代码之后,我可以明确地说,您将无法绝对可靠地完成这项工作,而且您当然也无法检测到RFC允许的所有URI格式。幸运的是,由于您感兴趣的URL集非常有限,因此可以使用上面的任何技术。

    但是,我可以非常肯定地说,如果你真的想打败垃圾邮件发送者,最好的方法就是使用javascript。发送一块执行某些计算的javascript,然后在服务器端重复计算。javascript应该将计算结果复制到一个隐藏字段,以便在提交注释时,也提交计算结果。在服务器端验证计算是否正确。解决这一技术的唯一方法是让垃圾邮件发送者手动输入评论,或者让他们开始为您运行一个javascript引擎。我使用这项技术将我网站上的垃圾邮件从每天100多封减少到每年一两封。现在我唯一收到的垃圾邮件是人工输入的。讨论垃圾话题很奇怪。

        9
  •  1
  •   Rad    15 年前

    当然,你会意识到,如果垃圾邮件发送者决定使用tinuyrl或类似的服务来缩短他们的网址,你的问题就会变得更糟。在这种情况下,您可能需要编写一些代码来查找实际的URL,使用类似这样的服务 TinyURL 译码器

        10
  •  1
  •   McGovernTheory    15 年前

    考虑合并OWASP Antisamy API…

        11
  •  1
  •   NickZoic    15 年前

    我喜欢 卡帕 目前为止最好的答案是,但是处理Unicode字体可能有点麻烦,旧浏览器经常显示有趣的东西或一个小盒子…U+05B4的位置有点奇怪…对我来说,它出现在管道外面,尽管它在管道之间。

    不过,还有一个方便的·(·),它可以用同样的方式断开剪切和粘贴。它的垂直对齐可以通过使用它来更正,例如:

    栈溢出 · 通用域名格式

    反常,但在ff3中仍然有效,它不能作为URL剪切和粘贴。sub<非常好,因为它在视觉上很明显地说明了为什么不能粘贴URL。

    不在可疑URL中的点可以单独使用,例如您可以这样做

    s/\b\.\b/<sub>&middot;<\/sub>/g
    

    另一种选择是在可疑点旁边插入某种零宽度实体,但像‍和‌和&ampzwsp;这样的东西在ff3中似乎不起作用。

        12
  •  1
  •   Tracker1    15 年前

    这里已经有一些很好的答案了,所以我不会再发了。不过,我还是会给你一些建议。首先,确保测试 已知的 协议,任何其他东西都可能是调皮的。作为一个爱好涉及telnet链接的人,您可能希望在搜索中包含多于http的内容,但可能希望阻止say aim:或其他一些URL。第二,许多人会用尖括号(gt/lt)像<一样来界定链接。 http://theroughnecks.net >或者在parens“(url)”中,没有什么比单击一个链接并关闭>或)与URL的其余部分一起分配更糟糕的了。

    P.S.对不起,自参考插头;)

        13
  •  0
  •   Hauke    6 年前

    我只需要检测带有/out协议的简单HTTP URL,假设协议是给定的或是“www”前缀。我发现了 above 提到 link 很有帮助,但最后我得出结论:

    http(s?)://(\S+\.)+\S+|www\d?\.(\S+\.)+\S+
    

    显然,这并不能测试是否符合DNS标准。