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

用javascript检测文本中的URL

  •  116
  • arbales  · 技术社区  · 15 年前

    是否有人建议在一组字符串中检测URL?

    arrayOfStrings.forEach(function(string){
      // detect URLs in strings and do something swell,
      // like creating elements with links.
    });
    

    更新: 几年后,我开始使用这个regex进行链接检测。

    kLINK_DETECTION_REGEX = /(([a-z]+:\/\/)?(([a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&]*)?)?(#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(\s+|$)/gi
    

    完整助手(带可选把手支架)位于 gist #1654670 .

    8 回复  |  直到 7 年前
        1
  •  166
  •   Community Egal    7 年前

    首先,您需要一个与URL匹配的好regex。这很难做到。见 here , here here :

    …几乎所有内容都是有效的URL。那里 一些标点符号规则用于 把它分开。缺席任何 标点符号,您仍然有一个有效的 网址。

    仔细检查RFC,看看您是否 无法构造“无效”的URL。这个 规则非常灵活。

    例如 ::::: 是一个有效的URL。 路径是 ":::::" . 漂亮的 愚蠢的文件名,但有效的文件名。

    也, ///// 是有效的URL。这个 netloc(“主机名”)是 "" .这条路 是 "///" . 又一次,笨蛋。阿尔索 有效。此URL规范化为 “//” 这是等效的。

    类似的东西 "bad://///worse/////" 完全有效。哑巴但有效。

    无论如何,这个答案并不意味着给你最好的regex,而是一个如何用javascript在文本中包装字符串的证明。

    好吧,我们就用这个: /(https?:\/\/[^\s]+)/g

    再一次, 这是个坏瑞格 . 它会有很多误报。但是对于这个例子来说已经足够好了。

    function urlify(text) {
        var urlRegex = /(https?:\/\/[^\s]+)/g;
        return text.replace(urlRegex, function(url) {
            return '<a href="' + url + '">' + url + '</a>';
        })
        // or alternatively
        // return text.replace(urlRegex, '<a href="$1">$1</a>')
    }
    
    var text = "Find me at http://www.example.com and also at http://stackoverflow.com";
    var html = urlify(text);
    
    // html now looks like:
    // "Find me at <a href="http://www.example.com">http://www.example.com</a> and also at <a href="http://stackoverflow.com">http://stackoverflow.com</a>"
    

    所以尝试一下:

    $$('#pad dl dd').each(function(element) {
        element.innerHTML = urlify(element.innerHTML);
    });
    
        2
  •  108
  •   skierpage    9 年前

    以下是我作为正则表达式使用的结果:

    var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
    

    这不包括URL中的尾随标点。新月形的功能就像是一种魅力:) 所以:

    function linkify(text) {
        var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
        return text.replace(urlRegex, function(url) {
            return '<a href="' + url + '">' + url + '</a>';
        });
    }
    
        3
  •  41
  •   Adam    10 年前

    我在google上搜索了很长一段时间,然后我发现有一个android方法,android.text.util.linkify,它使用一些非常健壮的regex来完成这个任务。幸运的是,Android是开源的。

    它们使用一些不同的模式来匹配不同类型的URL。你可以在这里找到它们: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/text/util/Regex.java#Regex.0WEB_URL_PATTERN

    如果您只关心与web_url_模式匹配的url,即符合RFC 1738规范的url,则可以使用:

    /((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi;
    

    以下是源文件的全文:

    "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
    + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
    + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
    + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+"   // named host
    + "(?:"   // plus top level domain
    + "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
    + "|(?:biz|b[abdefghijmnorstvwyz])"
    + "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
    + "|d[ejkmoz]"
    + "|(?:edu|e[cegrstu])"
    + "|f[ijkmor]"
    + "|(?:gov|g[abdefghilmnpqrstuwy])"
    + "|h[kmnrtu]"
    + "|(?:info|int|i[delmnoqrst])"
    + "|(?:jobs|j[emop])"
    + "|k[eghimnrwyz]"
    + "|l[abcikrstuvy]"
    + "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
    + "|(?:name|net|n[acefgilopruz])"
    + "|(?:org|om)"
    + "|(?:pro|p[aefghklmnrstwy])"
    + "|qa"
    + "|r[eouw]"
    + "|s[abcdeghijklmnortuvyz]"
    + "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
    + "|u[agkmsyz]"
    + "|v[aceginu]"
    + "|w[fs]"
    + "|y[etu]"
    + "|z[amw]))"
    + "|(?:(?:25[0-5]|2[0-4]" // or ip address
    + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
    + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
    + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
    + "|[1-9][0-9]|[0-9])))"
    + "(?:\\:\\d{1,5})?)" // plus option port number
    + "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~"  // plus option query params
    + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
    + "(?:\\b|$)";
    

    如果你真的想成为一个花花公子,你也可以测试电子邮件地址。电子邮件地址的regex是:

    /[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}\\@[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}(\\.[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25})+/gi
    

    PS:以上regex支持的顶级域截至2007年6月是最新的。要获得最新的列表,您需要检查 https://data.iana.org/TLD/tlds-alpha-by-domain.txt .

        4
  •  18
  •   h0mayun    10 年前

    基于 月牙鲜 回答

    如果要检测链接 用http:// 没有http://www. 您可以使用以下内容

    function urlify(text) {
        var urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g;
        //var urlRegex = /(https?:\/\/[^\s]+)/g;
        return text.replace(urlRegex, function(url,b,c) {
            var url2 = (c == 'www.') ?  'http://' +url : url;
            return '<a href="' +url2+ '" target="_blank">' + url + '</a>';
        }) 
    }
    
        5
  •  10
  •   Dan Kantor    7 年前

    这个关于NPM的图书馆看起来很全面 https://www.npmjs.com/package/linkifyjs

    Linkify是一个小而全面的javascript插件,用于查找纯文本中的URL并将其转换为HTML链接。它适用于所有有效的URL和电子邮件地址。

        6
  •  5
  •   Gautam Sharma    12 年前

    还可以进一步改进函数来渲染图像:

    function renderHTML(text) { 
        var rawText = strip(text)
        var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
    
        return rawText.replace(urlRegex, function(url) {   
    
        if ( ( url.indexOf(".jpg") > 0 ) || ( url.indexOf(".png") > 0 ) || ( url.indexOf(".gif") > 0 ) ) {
                return '<img src="' + url + '">' + '<br/>'
            } else {
                return '<a href="' + url + '">' + url + '</a>' + '<br/>'
            }
        }) 
    } 
    

    或者对于链接到全尺寸图像的缩略图:

    return '<a href="' + url + '"><img style="width: 100px; border: 0px; -moz-border-radius: 5px; border-radius: 5px;" src="' + url + '">' + '</a>' + '<br/>'
    

    这里是strip()函数,它通过删除任何现有的HTML来预处理文本字符串以获得一致性。

    function strip(html) 
        {  
            var tmp = document.createElement("DIV"); 
            tmp.innerHTML = html; 
            var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
            return tmp.innerText.replace(urlRegex, function(url) {     
            return '\n' + url 
        })
    } 
    
        7
  •  1
  •   Án Bình Trọng    10 年前

    tmp.innerText未定义。您应该使用tmp.innerhtml

    function strip(html) 
        {  
            var tmp = document.createElement("DIV"); 
            tmp.innerHTML = html; 
            var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
            return tmp.innerHTML .replace(urlRegex, function(url) {     
            return '\n' + url 
        })
    
        8
  •  0
  •   kofifus    7 年前

    试试这个:

    function isUrl(s) {
        if (!isUrl.rx_url) {
            // taken from https://gist.github.com/dperini/729294
            isUrl.rx_url=/^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i;
            // valid prefixes
            isUrl.prefixes=['http:\/\/', 'https:\/\/', 'ftp:\/\/', 'www.'];
            // taken from https://w3techs.com/technologies/overview/top_level_domain/all
            isUrl.domains=['com','ru','net','org','de','jp','uk','br','pl','in','it','fr','au','info','nl','ir','cn','es','cz','kr','ua','ca','eu','biz','za','gr','co','ro','se','tw','mx','vn','tr','ch','hu','at','be','dk','tv','me','ar','no','us','sk','xyz','fi','id','cl','by','nz','il','ie','pt','kz','io','my','lt','hk','cc','sg','edu','pk','su','bg','th','top','lv','hr','pe','club','rs','ae','az','si','ph','pro','ng','tk','ee','asia','mobi'];
        }
    
        if (!isUrl.rx_url.test(s)) return false;
        for (let i=0; i<isUrl.prefixes.length; i++) if (s.startsWith(isUrl.prefixes[i])) return true;
        for (let i=0; i<isUrl.domains.length; i++) if (s.endsWith('.'+isUrl.domains[i]) || s.includes('.'+isUrl.domains[i]+'\/') ||s.includes('.'+isUrl.domains[i]+'?')) return true;
        return false;
    }
    
    function isEmail(s) {
        if (!isEmail.rx_email) {
            // taken from http://stackoverflow.com/a/16016476/460084
            var sQtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
            var sDtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
            var sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
            var sQuotedPair = '\\x5c[\\x00-\\x7f]';
            var sDomainLiteral = '\\x5b(' + sDtext + '|' + sQuotedPair + ')*\\x5d';
            var sQuotedString = '\\x22(' + sQtext + '|' + sQuotedPair + ')*\\x22';
            var sDomain_ref = sAtom;
            var sSubDomain = '(' + sDomain_ref + '|' + sDomainLiteral + ')';
            var sWord = '(' + sAtom + '|' + sQuotedString + ')';
            var sDomain = sSubDomain + '(\\x2e' + sSubDomain + ')*';
            var sLocalPart = sWord + '(\\x2e' + sWord + ')*';
            var sAddrSpec = sLocalPart + '\\x40' + sDomain; // complete RFC822 email address spec
            var sValidEmail = '^' + sAddrSpec + '$'; // as whole string
    
            isEmail.rx_email = new RegExp(sValidEmail);
        }
    
        return isEmail.rx_email.test(s);
    }
    

    还可以识别URL,例如 google.com , http://www.google.bla , http://google.bla , www.google.bla 但不是 google.bla