从字符串中提取主机名

333

我想匹配文本字符串中URL的根而不是整个URL。给定:

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

我想获取解析到 www.example.comexample.com 域的最后两个实例。

我听说正则表达式很慢,这将是页面上第二个正则表达式,所以如果有不使用正则表达式的方法,请告诉我。

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


2
建议更改接受的答案,以便于新来的人进入这个问题,因为Robin的答案更好。 - Digital Ninja
3
(也许你应该从你的问题中删除“听说正则表达式很慢”,这样你就不会向新手传递错误的观念,因为在基准测试中,正则表达式是最快的解决方案。) - Digital Ninja
30个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
2
简而言之,您可以这样做。
var url = "http://www.someurl.com/support/feature"

function getDomain(url){
  domain=url.split("//")[1];
  return domain.split("/")[0];
}
eg:
  getDomain("http://www.example.com/page/1")

  output:
   "www.example.com"
使用上述函数获取域名。

什么是问题? - uzaif
问题在于如果在问号前面没有斜杠,它就无法工作。 - Toolkit
在你的情况下,你需要检查域名字符串中的 ?,并且将 return domain.split("/")[0]; 替换为 return domain.split("?")[0];,希望它可以工作。 - uzaif

1
这个解决方案很有效,如果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(parsed)

output:

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

与https://dev59.com/FWoy5IYBdhLWcg3wg-Ym#23945027相同,`psl`速度慢+重。请参考https://bundlephobia.com/package/psl@1.9.0。 - Robin Métral

1
import URL from 'url';

const pathname = URL.parse(url).path;
console.log(url.replace(pathname, ''));
这个可以同时处理协议的问题。

这个模块是 NodeJS 自带的。 - djibe
1
这是一个遗留的NodeJS API(查看文档)。更新的WHATWG API与浏览器中的相同:不要导入“url”,只需使用构造函数:new URL()。它已经在其他答案中广泛涵盖。最后,问题是关于获取主机名,但这个答案只删除了路径(这不是同一件事)。被踩了。 - Robin Métral


0
一个URL是schema://domain/path/to/resource?key=value#fragment,因此你可以在/上进行分割。
/**
 * Get root of URL
 * @param {string} url - string to parse
 * @returns {string} url root or empty string
 */
function getUrlRoot(url) {
  return String(url || '').split('/').slice(0, 3).join('/');
}

例子:

getUrlRoot('http://www.youtube.com/watch?v=ClkQA2Lb_iE');
// returns http://www.youtube.com

getUrlRoot('http://youtu.be/ClkQA2Lb_iE');
// returns http://youtu.be

getUrlRoot('http://www.example.com/12xy45');
// returns http://www.example.com

getUrlRoot('http://example.com/random');
// returns http://example.com

0

代码:

var regex = /\w+.(com|co\.kr|be)/ig;
var urls = ['http://www.youtube.com/watch?v=ClkQA2Lb_iE',
            'http://youtu.be/ClkQA2Lb_iE',
            'http://www.example.com/12xy45',
            'http://example.com/random'];


$.each(urls, function(index, url) {
    var convertedUrl = url.match(regex);
    console.log(convertedUrl);
});

结果:

youtube.com
youtu.be
example.com
example.com

相反,OP提到了正则表达式,这很明显是一个正则表达式,旨在匹配URL的请求部分。它并不完全正确(例如,它需要www.,即使不是所有URL都有这个组件),但它肯定是一个答案 - Kyle Strand
@KyleStrand “Pretty obviously”是一个主观判断;当被问到“我正在寻找这个解决方案的JS / jQuery版本”时,提供原始正则表达式并不能回答问题。 - Christian Ternus
我是楼主。当时我是一名新的开发者,正在寻找JS中的一个开箱即用的解决方案。事实上,一个没有任何上下文的原始正则表达式字符串根本没有帮助。而且它是不完整的。 - Chamilyan

0

parse-domain - 一个非常稳定的轻量级库

npm install parse-domain

const { fromUrl, parseDomain } = require("parse-domain");

示例1

parseDomain(fromUrl("http://www.example.com/12xy45"))
{ type: 'LISTED',
  hostname: 'www.example.com',
  labels: [ 'www', 'example', 'com' ],
  icann:
   { subDomains: [ 'www' ],
     domain: 'example',
     topLevelDomains: [ 'com' ] },
  subDomains: [ 'www' ],
  domain: 'example',
  topLevelDomains: [ 'com' ] }

示例2

parseDomain(fromUrl("http://subsub.sub.test.ExAmPlE.coM/12xy45"))
{ type: 'LISTED',
  hostname: 'subsub.sub.test.example.com',
  labels: [ 'subsub', 'sub', 'test', 'example', 'com' ],
  icann:
   { subDomains: [ 'subsub', 'sub', 'test' ],
     domain: 'example',
     topLevelDomains: [ 'com' ] },
  subDomains: [ 'subsub', 'sub', 'test' ],
  domain: 'example',
  topLevelDomains: [ 'com' ] }

为什么?

根据使用情况和数量,我强烈建议不要使用正则表达式或其他字符串操作方式来解决这个问题。这个问题的核心是你需要知道所有的gtld和cctld后缀,以便将URL字符串正确解析为域名和子域名,这些后缀经常更新。这是一个已解决的问题,而且不是你想自己解决的问题(除非你是谷歌或类似的公司)。除非你在紧急情况下需要主机名或域名,否则不要试图通过解析来解决这个问题。


0
简单:
const url = new URL("https://www.magicspoon.com/pages/miss-cereal-new-bday");
domainUrl = url.hostname?.split(".").slice(-2).join(".");
//domainUrl: magicspoon.com
--- 
const url = new URL("https://magicspoon.com/pages/miss-cereal-new-bday");
domainUrl = url.hostname?.split(".").slice(-2).join(".");
//domainUrl: magicspoon.com

请在您的代码中加入一些解释,而不是仅仅贴上代码。额外的解释将更有帮助。 - user67275

-2

我的代码看起来像这样。 正则表达式可以有很多形式,以下是我的测试用例。 我认为这更具可扩展性。

function extractUrlInfo(url){
  let reg = /^((?<protocol>http[s]?):\/\/)?(?<host>((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])|[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)))(\:(?<port>[0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5]))?$/
  return reg.exec(url).groups
}

var url = "https://192.168.1.1:1234"
console.log(extractUrlInfo(url))
var url = "https://dev59.com/FWoy5IYBdhLWcg3wg-Ym"
console.log(extractUrlInfo(url))


这不是主机名。它应该是stackoverflow.com。你所拥有的是主机名+路径名。 - Robin Métral

-6

使用正则表达式尝试以下代码以获取精确的域名:

String 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");
  }

3
OP 寻找的是 JavaScript 的答案,而不是 Java。 - piersadrian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,