我想匹配的只是一个URL的根,而不是一个文本字符串的整个URL。考虑到:

http://www.youtube.com/watch?v=ClkQA2Lb_iE
http://youtu.be/ClkQA2Lb_iE
http://www.example.com/12xy45
http://example.com/random

我想让最后2个实例解析到www.example.com或example.com域。

我听说正则表达式很慢,这将是我在页面上的第二个正则表达式,所以如果有办法做到没有正则表达式,请告诉我。

我正在寻找这个解决方案的JS/jQuery版本。


当前回答

不需要解析字符串,只需将URL作为参数传递给URL构造函数:

const url = 'http://www.youtube.com/watch?v=ClkQA2Lb_iE';
const { hostname } = new URL(url);

console.assert(hostname === 'www.youtube.com');

其他回答

我给你3个可能的解决方案:

使用npm包psl提取你扔给它的任何东西。 使用我的自定义实现extractRootDomain,它适用于大多数情况。 网址(URL)。主机名是可行的,但并非适用于所有边缘情况。点击“运行代码段”查看它是如何运行的。

1. 使用npm包psl(公共后缀列表)

“公共后缀列表”是所有有效域名后缀和规则的列表,不仅是国家代码顶级域名,还包括被视为根域的unicode字符(即www.食狮.公司.cn, b.c.a bebe .jp等)。点击这里阅读更多信息。

Try:

npm install --save psl

然后用我的“extractHostname”实现运行:

let psl = require('psl');
let url = 'http://www.youtube.com/watch?v=ClkQA2Lb_iE';
psl.get(extractHostname(url)); // returns youtube.com

2. extractRootDomain的自定义实现

下面是我的实现,它还针对各种可能的URL输入运行。

function extractHostname(url) { var hostname; //find & remove protocol (http, ftp, etc.) and get hostname if (url.indexOf("//") > -1) { hostname = url.split('/')[2]; } else { hostname = url.split('/')[0]; } //find & remove port number hostname = hostname.split(':')[0]; //find & remove "?" hostname = hostname.split('?')[0]; return hostname; } // Warning: you can use this function to extract the "root" domain, but it will not be as accurate as using the psl package. function extractRootDomain(url) { var domain = extractHostname(url), splitArr = domain.split('.'), arrLen = splitArr.length; //extracting the root domain here //if there is a subdomain if (arrLen > 2) { domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1]; //check to see if it's using a Country Code Top Level Domain (ccTLD) (i.e. ".me.uk") if (splitArr[arrLen - 2].length == 2 && splitArr[arrLen - 1].length == 2) { //this is using a ccTLD domain = splitArr[arrLen - 3] + '.' + domain; } } return domain; } const urlHostname = url => { try { return new URL(url).hostname; } catch(e) { return e; } }; const urls = [ "http://www.blog.classroom.me.uk/index.php", "http://www.youtube.com/watch?v=ClkQA2Lb_iE", "https://www.youtube.com/watch?v=ClkQA2Lb_iE", "www.youtube.com/watch?v=ClkQA2Lb_iE", "ftps://ftp.websitename.com/dir/file.txt", "websitename.com:1234/dir/file.txt", "ftps://websitename.com:1234/dir/file.txt", "example.com?param=value", "https://facebook.github.io/jest/", "//youtube.com/watch?v=ClkQA2Lb_iE", "www.食狮.公司.cn", "b.c.kobe.jp", "a.d.kyoto.or.jp", "http://localhost:4200/watch?v=ClkQA2Lb_iE" ]; const test = (method, arr) => console.log( `=== Testing "${method.name}" ===\n${arr.map(url => method(url)).join("\n")}\n`); test(extractHostname, urls); test(extractRootDomain, urls); test(urlHostname, urls);

无论是否有协议或端口号,您都可以提取域。这是一个非常简化的,非正则表达式的解,所以我认为这可以解决我们在问题中提供的数据集。

3. 网址(URL) hostname

网址(URL)。主机名是一个有效的解决方案,但它不适用于我已经解决的一些边缘情况。正如您在上次测试中看到的,它不喜欢某些url。你绝对可以使用我的解决方案的组合来让它全部工作。

*感谢@Timmerz, @renoirb, @rineez, @BigDong, @ra00l, @ILikeBeansTacos, @CharlesRobertson的建议!@ross-allen,谢谢你报告这个bug!

function hostname(url) {
    var match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i);
    if ( match != null && match.length > 2 && typeof match[2] === 'string' && match[2].length > 0 ) return match[2];
}

上面的代码将成功解析以下示例url的主机名: http://WWW.first.com/folder/page.html first.com http://mail.google.com/folder/page.html mail.google.com https://mail.google.com/folder/page.html mail.google.com http://www2.somewhere.com/folder/page.html?q=1 somewhere.com https://www.another.eu/folder/page.html?q=1 another.eu

原文出处:http://www.primaryobjects.com/CMS/Article145

这个解决方案工作得很好,如果URL包含大量无效字符,您也可以使用。

安装PSL包

npm install --save psl

实现

const psl = require('psl');

const url= new URL('http://www.youtube.com/watch?v=ClkQA2Lb_iE').hostname;
const parsed = psl.parse(url);

console.log(解析)

输出:

{
  input: 'www.youtube.com',
  tld: 'com',
  sld: 'youtube',
  domain: 'youtube.com',
  subdomain: 'www',
  listed: true
}

尝试下面的代码为精确的域名使用正则表达式,

字符串line = "http://www.youtube.com/watch?v=ClkQA2Lb_iE";

  String pattern3="([\\w\\W]\\.)+(.*)?(\\.[\\w]+)";

  Pattern r = Pattern.compile(pattern3);


  Matcher m = r.matcher(line);
  if (m.find( )) {

    System.out.println("Found value: " + m.group(2) );
  } else {
     System.out.println("NO MATCH");
  }

试试这个:

var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
var domain = matches && matches[1];  // domain will be null if no match is found

如果你想从结果中排除端口,请使用下面的表达式:

/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i

编辑:要防止特定域匹配,请使用反向前向。(? ! youtube.com)

/^https?\:\/\/(?!(?:www\.)?(?:youtube\.com|youtu\.be))([^\/:?#]+)(?:[\/:?#]|$)/i