我给你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!