我想匹配的只是一个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版本。


试试这个:

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

解析URL可能很棘手,因为您可以使用端口号和特殊字符。因此,我建议使用parseUri之类的东西来做这个。我怀疑性能不会成为问题,除非您要解析数百个url。


一个不用正则表达式的小技巧:

var tmp        = document.createElement ('a');
;   tmp.href   = "http://www.example.com/12xy45";

// tmp.hostname will now contain 'www.example.com'
// tmp.host will now contain hostname and port 'www.example.com:80'

将上述内容包装在如下函数中,您就拥有了从URI中获取域部分的绝佳方法。

function url_domain(data) {
  var    a      = document.createElement('a');
         a.href = data;
  return a.hostname;
}

// use this if you know you have a subdomain
// www.domain.com -> domain.com
function getDomain() {
  return window.location.hostname.replace(/([a-zA-Z0-9]+.)/,"");
}

我尝试使用给定的解决方案,选择的解决方案对我的目的来说是多余的,而“创建一个元素”对我来说是一团糟。

它还没有准备好在URL的端口。我希望有人觉得它有用

function parseURL(url){
    parsed_url = {}

    if ( url == null || url.length == 0 )
        return parsed_url;

    protocol_i = url.indexOf('://');
    parsed_url.protocol = url.substr(0,protocol_i);

    remaining_url = url.substr(protocol_i + 3, url.length);
    domain_i = remaining_url.indexOf('/');
    domain_i = domain_i == -1 ? remaining_url.length - 1 : domain_i;
    parsed_url.domain = remaining_url.substr(0, domain_i);
    parsed_url.path = domain_i == -1 || domain_i + 1 == remaining_url.length ? null : remaining_url.substr(domain_i + 1, remaining_url.length);

    domain_parts = parsed_url.domain.split('.');
    switch ( domain_parts.length ){
        case 2:
          parsed_url.subdomain = null;
          parsed_url.host = domain_parts[0];
          parsed_url.tld = domain_parts[1];
          break;
        case 3:
          parsed_url.subdomain = domain_parts[0];
          parsed_url.host = domain_parts[1];
          parsed_url.tld = domain_parts[2];
          break;
        case 4:
          parsed_url.subdomain = domain_parts[0];
          parsed_url.host = domain_parts[1];
          parsed_url.tld = domain_parts[2] + '.' + domain_parts[3];
          break;
    }

    parsed_url.parent_domain = parsed_url.host + '.' + parsed_url.tld;

    return parsed_url;
}

运行:

parseURL('https://www.facebook.com/100003379429021_356001651189146');

结果:

Object {
    domain : "www.facebook.com",
    host : "facebook",
    path : "100003379429021_356001651189146",
    protocol : "https",
    subdomain : "www",
    tld : "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!


String.prototype.trim = function(){return his.replace(/^\s+|\s+$/g,"");}
function getHost(url){
    if("undefined"==typeof(url)||null==url) return "";
    url = url.trim(); if(""==url) return "";
    var _host,_arr;
    if(-1<url.indexOf("://")){
        _arr = url.split('://');
        if(-1<_arr[0].indexOf("/")||-1<_arr[0].indexOf(".")||-1<_arr[0].indexOf("\?")||-1<_arr[0].indexOf("\&")){
            _arr[0] = _arr[0].trim();
            if(0==_arr[0].indexOf("//")) _host = _arr[0].split("//")[1].split("/")[0].trim().split("\?")[0].split("\&")[0];
            else return "";
        }
        else{
            _arr[1] = _arr[1].trim();
            _host = _arr[1].split("/")[0].trim().split("\?")[0].split("\&")[0];
        }
    }
    else{
        if(0==url.indexOf("//")) _host = url.split("//")[1].split("/")[0].trim().split("\?")[0].split("\&")[0];
        else return "";
    }
    return _host;
}
function getHostname(url){
    if("undefined"==typeof(url)||null==url) return "";
    url = url.trim(); if(""==url) return "";
    return getHost(url).split(':')[0];
}
function getDomain(url){
    if("undefined"==typeof(url)||null==url) return "";
    url = url.trim(); if(""==url) return "";
    return getHostname(url).replace(/([a-zA-Z0-9]+.)/,"");
}

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试试这个:

^(?:https?:)?(?:\/\/)?([^\/\?]+)

https://regex101.com/r/pX5dL9/1

你可以像下面这样使用它,也可以用不区分大小写的方式来匹配HTTPS和HTTP:

const match = str.match(/^(?:https?:)?(?:\/\/)?([^\/\?]+)/i);
const hostname = match && match[1];

它适用于url没有http://,与http,与https,与只是//和不抓取路径和查询路径以及。

祝你好运


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

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

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

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

字符串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 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"

使用上述函数获取域名


代码:

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

好吧,我知道这是一个老问题,但我做了一个超级高效的url解析器,所以我想我要分享它。

如你所见,这个函数的结构很奇怪,但这是为了提高效率。不使用原型函数,字符串迭代次数不超过一次,处理字符的次数也不超过必要的次数。

function getDomain(url) {
    var dom = "", v, step = 0;
    for(var i=0,l=url.length; i<l; i++) {
        v = url[i]; if(step == 0) {
            //First, skip 0 to 5 characters ending in ':' (ex: 'https://')
            if(i > 5) { i=-1; step=1; } else if(v == ':') { i+=2; step=1; }
        } else if(step == 1) {
            //Skip 0 or 4 characters 'www.'
            //(Note: Doesn't work with www.com, but that domain isn't claimed anyway.)
            if(v == 'w' && url[i+1] == 'w' && url[i+2] == 'w' && url[i+3] == '.') i+=4;
            dom+=url[i]; step=2;
        } else if(step == 2) {
            //Stop at subpages, queries, and hashes.
            if(v == '/' || v == '?' || v == '#') break; dom += v;
        }
    }
    return dom;
}

今天正在寻找解决这个问题的方法。上述答案似乎都不令人满意。我想要一个解决方案,可以是一行,没有条件逻辑,没有什么必须包装在一个函数。

这是我想到的,似乎真的很有效:

hostname="http://www.example.com:1234"
hostname.split("//").slice(-1)[0].split(":")[0].split('.').slice(-2).join('.')   // gives "example.com"

乍一看可能很复杂,但它的工作原理很简单;关键是在一些地方使用'slice(-n)',在这些地方,好的部分必须从拆分数组的末尾取出([0]从拆分数组的前面取出)。

这些测试都返回"example.com":

"http://example.com".split("//").slice(-1)[0].split(":")[0].split('.').slice(-2).join('.')
"http://example.com:1234".split("//").slice(-1)[0].split(":")[0].split('.').slice(-2).join('.')
"http://www.example.com:1234".split("//").slice(-1)[0].split(":")[0].split('.').slice(-2).join('.')
"http://foo.www.example.com:1234".split("//").slice(-1)[0].split(":")[0].split('.').slice(-2).join('.')

下面是jQuery的一行代码:

$('<a>').attr('href', url).prop('hostname');

这不是一个完整的答案,但下面的代码应该会帮助你:

function myFunction() {
    var str = "https://www.123rf.com/photo_10965738_lots-oop.html";
    matches = str.split('/');
    return matches[2];
}

我想有人比我更快地创建代码。它也有助于提高我自己。


所有url属性,没有依赖,没有JQuery,容易理解

这个解决方案给了你的答案和额外的性质。不需要JQuery或其他依赖,粘贴和走。

使用

getUrlParts("https://news.google.com/news/headlines/technology.html?ned=us&hl=en")

输出

{
  "origin": "https://news.google.com",
  "domain": "news.google.com",
  "subdomain": "news",
  "domainroot": "google.com",
  "domainpath": "news.google.com/news/headlines",
  "tld": ".com",
  "path": "news/headlines/technology.html",
  "query": "ned=us&hl=en",
  "protocol": "https",
  "port": 443,
  "parts": [
    "news",
    "google",
    "com"
  ],
  "segments": [
    "news",
    "headlines",
    "technology.html"
  ],
  "params": [
    {
      "key": "ned",
      "val": "us"
    },
    {
      "key": "hl",
      "val": "en"
    }
  ]
}

代码 代码设计得很容易理解,而不是超级快。每秒可以轻松调用100次,因此它非常适合前端或少量服务器使用,但不适用于高容量吞吐量。

function getUrlParts(fullyQualifiedUrl) {
    var url = {},
        tempProtocol
    var a = document.createElement('a')
    // if doesn't start with something like https:// it's not a url, but try to work around that
    if (fullyQualifiedUrl.indexOf('://') == -1) {
        tempProtocol = 'https://'
        a.href = tempProtocol + fullyQualifiedUrl
    } else
        a.href = fullyQualifiedUrl
    var parts = a.hostname.split('.')
    url.origin = tempProtocol ? "" : a.origin
    url.domain = a.hostname
    url.subdomain = parts[0]
    url.domainroot = ''
    url.domainpath = ''
    url.tld = '.' + parts[parts.length - 1]
    url.path = a.pathname.substring(1)
    url.query = a.search.substr(1)
    url.protocol = tempProtocol ? "" : a.protocol.substr(0, a.protocol.length - 1)
    url.port = tempProtocol ? "" : a.port ? a.port : a.protocol === 'http:' ? 80 : a.protocol === 'https:' ? 443 : a.port
    url.parts = parts
    url.segments = a.pathname === '/' ? [] : a.pathname.split('/').slice(1)
    url.params = url.query === '' ? [] : url.query.split('&')
    for (var j = 0; j < url.params.length; j++) {
        var param = url.params[j];
        var keyval = param.split('=')
        url.params[j] = {
            'key': keyval[0],
            'val': keyval[1]
        }
    }
    // domainroot
    if (parts.length > 2) {
        url.domainroot = parts[parts.length - 2] + '.' + parts[parts.length - 1];
        // check for country code top level domain
        if (parts[parts.length - 1].length == 2 && parts[parts.length - 1].length == 2)
            url.domainroot = parts[parts.length - 3] + '.' + url.domainroot;
    }
    // domainpath (domain+path without filenames) 
    if (url.segments.length > 0) {
        var lastSegment = url.segments[url.segments.length - 1]
        var endsWithFile = lastSegment.indexOf('.') != -1
        if (endsWithFile) {
            var fileSegment = url.path.indexOf(lastSegment)
            var pathNoFile = url.path.substr(0, fileSegment - 1)
            url.domainpath = url.domain
            if (pathNoFile)
                url.domainpath = url.domainpath + '/' + pathNoFile
        } else
            url.domainpath = url.domain + '/' + url.path
    } else
        url.domainpath = url.domain
    return url
}

我个人对这个解决方案做了很多研究,我能找到的最好的解决方案实际上来自CloudFlare的“浏览器检查”:

function getHostname(){  
            secretDiv = document.createElement('div');
            secretDiv.innerHTML = "<a href='/'>x</a>";
            secretDiv = secretDiv.firstChild.href;
            var HasHTTPS = secretDiv.match(/https?:\/\//)[0];
            secretDiv = secretDiv.substr(HasHTTPS.length);
            secretDiv = secretDiv.substr(0, secretDiv.length - 1);
            return(secretDiv);  
}  

getHostname();

我重写了变量,使它更“人类”可读,但它比预期的工作做得更好。


jquery Oneline

$('<a>').attr('href', document.location.href).prop('hostname');

好吧,使用正则表达式会容易得多:

    mainUrl = "http://www.mywebsite.com/mypath/to/folder";
    urlParts = /^(?:\w+\:\/\/)?([^\/]+)(.*)$/.exec(mainUrl);
    host = Fragment[1]; // www.mywebsite.com

有两个很好的解决方案,这取决于你是否需要优化性能(并且没有外部依赖!):

1. 使用URL。便于阅读的主机名

最简洁和最简单的解决方案是使用URL.hostname。

getHostname = (url) => { //使用URL构造函数并返回主机名 返回新URL(URL).hostname; } / /测试 console.log (getHostname (" https://stackoverflow.com/questions/8498592/extract-hostname-name-from-string/ ")); console.log (getHostname (" https://developer.mozilla.org/en-US/docs/Web/API/URL/hostname "));

URL。主机名是URL API的一部分,除IE (caniuse)之外的所有主流浏览器都支持。如果需要支持旧浏览器,请使用URL填充。

额外的好处:使用URL构造函数还可以让你访问其他URL属性和方法!


2. 使用RegEx来提高性能

URL。对于大多数用例,主机名应该是您的选择。然而,它仍然比这个正则表达式慢得多(你自己在jsPerf上测试):

const getHostnameFromRegex = (url) => { //运行正则表达式 const匹配= url.match (/ ^ https ?\:\/\/([^\/?#]+)(?:[\/?#]|$)/ 我); //提取主机名(如果没有匹配则为空) 返回匹配&&匹配[1]; } / /测试 console.log (getHostnameFromRegex (" https://stackoverflow.com/questions/8498592/extract-hostname-name-from-string/ ")); console.log (getHostnameFromRegex (" https://developer.mozilla.org/en-US/docs/Web/API/URL/hostname "));


博士TL;

你应该使用URL.hostname。如果您需要处理大量的url(其中性能是一个因素),请考虑RegEx。


Parse-Urls似乎是具有最健壮模式的JavaScript库

以下是功能概述:

第1章。规范化或解析一个URL

第二章。提取所有url

第三章。提取具有特定名称的uri

第四章。提取所有模糊url

第五章。突出显示文本中的所有url

第六章。提取原始HTML或XML中的所有url


只需使用URL()构造函数:

new URL(url).host

解析域——一个非常可靠的轻量级库

NPM安装解析域

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' ] }

Why?

Depending on the use case and volume I strongly recommend against solving this problem yourself using regex or other string manipulation means. The core of this problem is that you need to know all the gtld and cctld suffixes to properly parse url strings into domain and subdomains, these suffixes are regularly updated. This is a solved problem and not one you want to solve yourself (unless you are google or something). Unless you need the hostname or domain name in a pinch don't try and parse your way out of this one.


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

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://stackoverflow.com/questions/8498592/extract-hostname-name-from-string" console.log(extractUrlInfo(url))


import URL from 'url';

const pathname = URL.parse(url).path;
console.log(url.replace(pathname, ''));

这样就兼顾了协议。


这个解决方案工作得很好,如果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
}