使用JavaScript检测文字中的网址

有没有人有建议检测一组字符串中的网址?

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

更新:我使用这个正则表达式链接检测…显然几年后。

 kLINK_DETECTION_REGEX = /(([az]+:\/\/)?(([a-z0-9\-]+\.)+([az]{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 

完整的帮手(可选​​的把手支持)在要点#1654670 。

首先,你需要一个好的正则表达式来匹配url。 这很难做到。 看到这里 , 在这里和这里 :

几乎任何东西都是有效的URL。 有一些标点符号规则将其分开。 缺少任何标点符号,您仍然有一个有效的网址。

仔细检查RFC,看看是否可以构建一个“无效的”URL。 规则非常灵活。

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

另外, /////是一个有效的URL。 netloc(“主机名”)是"" 。 路径是"///" 。 再次,愚蠢。 也有效。 这个URL标准化为"///" ,这是等效的。

"bad://///worse/////"这样的东西是完全有效的。 愚蠢但有效。

无论如何,这个答案并不意味着给你最好的正则表达式,而是一个如何使用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); }); 

这是我最终使用的正则表达式:

 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>'; }); } 

我搜索了这个问题很长一段时间,然后发现有一个Android方法,android.text.util.Linkify,利用一些非常强大的正则表达式来实现这一点。 幸运的是,Android是开源的。

他们使用一些不同的模式来匹配不同类型的网址。 你可以在这里找到它们: 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_PATTERN匹配的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|$)"; 

如果你想要真的很喜欢,你也可以测试电子邮件地址。 电子邮件地址的正则表达式是:

 /[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:以上正则表达式支持的顶级域名截止2007年6月是最新的。对于最新的列表,你需要检查https://data.iana.org/TLD/tlds-alpha-by-domain.txt

基于新月新鲜的答案

如果你想检测链接与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>'; }) } 

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

 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 }) } 

NPM上的这个库看起来像是相当全面的https://www.npmjs.com/package/linkifyjs

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

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 }) 

尝试这个:

 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]))|(?:(?:[az\u00a1-\uffff0-9]-*)*[az\u00a1-\uffff0-9]+)(?:\.(?:[az\u00a1-\uffff0-9]-*)*[az\u00a1-\uffff0-9]+)*(?:\.(?:[az\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); } 

还将识别诸如google.comhttp://www.google.bla http://google.bla ,但不包括google.bla