如何从URL获取域名

我如何从URLstring获取域名?

例子:

+----------------------+------------+ | input | output | +----------------------+------------+ | www.google.com | google | | www.mail.yahoo.com | mail.yahoo | | www.mail.yahoo.co.in | mail.yahoo | | www.abc.au.uk | abc | +----------------------+------------+ 

有关:

  • 通过正则expression式匹配url

我曾经为我工作的公司写过这样的正则expression式。 解决scheme是这样的:

  • 获取每个可用的ccTLD和gTLD列表。 你的第一站应该是IANA 。 从Mozilla的列表看起来很棒,但缺乏ac.uk,所以这不是真的可用。
  • 像下面的例子一样join列表。 警告:订购很重要! 如果org.uk会出现在英国之后,那么example.org.uk会匹配org而不是example

示例正则expression式:

 .*([^\.]+)(com|net|org|info|coop|int|co\.uk|org\.uk|ac\.uk|uk|__and so on__)$ 

这工作得很好,也匹配像de.com和朋友这样的怪异,非官方的顶层。

好处:

  • 如果正则expression式是非常快速的

这个解决scheme的缺点当然是:

  • 手写正则expression式,如果ccTLD更改或添加,必须手动更新。 单调乏味的工作!
  • 非常大的正则expression式,因此不太可读。
 /^(?:www\.)?(.*?)\.(?:com|au\.uk|co\.in)$/ 
 /* These are TLDs that have an SLD */ var tlds = { "cy":true, "ro":true, "ke":true, "kh":true, "ki":true, "cr":true, "km":true, "kn":true, "kr":true, "ck":true, "cn":true, "kw":true, "rs":true, "ca":true, "kz":true, "rw":true, "ru":true, "za":true, "zm":true, "bz":true, "je":true, "uy":true, "bs":true, "br":true, "jo":true, "us":true, "bh":true, "bo":true, "bn":true, "bb":true, "ba":true, "ua":true, "eg":true, "ec":true, "et":true, "er":true, "es":true, "pl":true, "in":true, "ph":true, "il":true, "pe":true, "co":true, "pa":true, "id":true, "py":true, "ug":true, "ky":true, "ir":true, "pt":true, "pw":true, "iq":true, "it":true, "pr":true, "sh":true, "sl":true, "sn":true, "sa":true, "sb":true, "sc":true, "sd":true, "se":true, "hk":true, "sg":true, "sy":true, "sz":true, "st":true, "sv":true, "om":true, "th":true, "ve":true, "tz":true, "vn":true, "vi":true, "pk":true, "fk":true, "fj":true, "fr":true, "ni":true, "ng":true, "nf":true, "re":true, "na":true, "qa":true, "tw":true, "nr":true, "np":true, "ac":true, "af":true, "ae":true, "ao":true, "al":true, "yu":true, "ar":true, "tj":true, "at":true, "au":true, "ye":true, "mv":true, "mw":true, "mt":true, "mu":true, "tr":true, "mz":true, "tt":true, "mx":true, "my":true, "mg":true, "me":true, "mc":true, "ma":true, "mn":true, "mo":true, "ml":true, "mk":true, "do":true, "dz":true, "ps":true, "lr":true, "tn":true, "lv":true, "ly":true, "lb":true, "lk":true, "gg":true, "uk":true, "gn":true, "gh":true, "gt":true, "gu":true, "jp":true, "gr":true, "nz":true } function isSecondLevelDomainPresent(domainParts) { return typeof tlds[domainParts[domainParts.length-1]] != "undefined"; } function getDomainFromHostname(url) { domainParts = url.split("."); var cutOff =2; if (isSecondLevelDomainPresent(domainParts)) { cutOff=3; } return domainParts.slice(domainParts.length-cutOff, domainParts.length).join("."); } 

为什么不select需要SLD的已知顶级域名(TLD)列表,而不是编写大型正则expression式,并从中构build一个哈希表。 然后当你分裂的url,你可以知道是否采取最后2件,或最后3个。

我不知道任何库,但域名的string操作是很容易的。

困难的部分是知道名字是在二级还是三级。 为此,您将需要一个您维护的数据文件(例如,.uk并不总是第三级,一些组织(例如bl.uk,jet.uk)存在于第二级)。

来自Mozilla 的Firefox的来源有这样一个数据文件,检查Mozilla许可证,看看你是否可以重用。

 import urlparse GENERIC_TLDS = [ 'aero', 'asia', 'biz', 'com', 'coop', 'edu', 'gov', 'info', 'int', 'jobs', 'mil', 'mobi', 'museum', 'name', 'net', 'org', 'pro', 'tel', 'travel', 'cat' ] def get_domain(url): hostname = urlparse.urlparse(url.lower()).netloc if hostname == '': # Force the recognition as a full URL hostname = urlparse.urlparse('http://' + uri).netloc # Remove the 'user:passw', 'www.' and ':port' parts hostname = hostname.split('@')[-1].split(':')[0].lstrip('www.').split('.') num_parts = len(hostname) if (num_parts < 3) or (len(hostname[-1]) > 2): return '.'.join(hostname[:-1]) if len(hostname[-2]) > 2 and hostname[-2] not in GENERIC_TLDS: return '.'.join(hostname[:-1]) if num_parts >= 3: return '.'.join(hostname[:-2]) 

此代码不能保证与所有url一起使用,也不会过滤那些语法正确但无效的文件,例如“example.uk”。

但是在大多数情况下,它会做这个工作。

有两种方法

使用分割

然后parsing这个string

 var domain; //find & remove protocol (http, ftp, etc.) and get domain if (url.indexOf('://') > -1) { domain = url.split('/')[2]; } if (url.indexOf('//') === 0) { domain = url.split('/')[2]; } else { domain = url.split('/')[0]; } //find & remove port number domain = domain.split(':')[0]; 

使用正则expression式

  var r = /:\/\/(.[^/]+)/; "http://stackoverflow.com/questions/5343288/get-url".match(r)[1] => stackoverflow.com 

希望这可以帮助

正确提取域名可能相当棘手,主要是因为域名扩展名可以包含2个部分(如.com.au或.co.uk),子域名(前缀)可能会或可能不在。 列出所有域扩展名不是一个选项,因为有数百个这样的。 例如,EuroDNS.com列出了超过800个域名扩展名。

因此,我写了一个简短的PHP函数,使用“parse_url()”和一些关于域名扩展的观察来准确地提取URL组件和域名。 function如下:

 function parse_url_all($url){ $url = substr($url,0,4)=='http'? $url: 'http://'.$url; $d = parse_url($url); $tmp = explode('.',$d['host']); $n = count($tmp); if ($n>=2){ if ($n==4 || ($n==3 && strlen($tmp[($n-2)])<=3)){ $d['domain'] = $tmp[($n-3)].".".$tmp[($n-2)].".".$tmp[($n-1)]; $d['domainX'] = $tmp[($n-3)]; } else { $d['domain'] = $tmp[($n-2)].".".$tmp[($n-1)]; $d['domainX'] = $tmp[($n-2)]; } } return $d; } 

这个简单的function几乎可以在任何情况下工作。 有一些例外,但这些是非常罕见的。

为了演示/testing这个function,你可以使用下面的代码:

 $urls = array('www.test.com', 'test.com', 'cp.test.com' .....); echo "<div style='overflow-x:auto;'>"; echo "<table>"; echo "<tr><th>URL</th><th>Host</th><th>Domain</th><th>Domain X</th></tr>"; foreach ($urls as $url) { $info = parse_url_all($url); echo "<tr><td>".$url."</td><td>".$info['host']. "</td><td>".$info['domain']."</td><td>".$info['domainX']."</td></tr>"; } echo "</table></div>"; 

列出的URL的输出如下所示:

在这里输入图像描述

正如您所看到的那样,无论展示给该函数的URL如何,域名和没有扩展名的域名都会被一致地提取出来。

我希望这有助于。

基本上,你想要的是:

 google.com -> google.com -> google www.google.com -> google.com -> google google.co.uk -> google.co.uk -> google www.google.co.uk -> google.co.uk -> google www.google.org -> google.org -> google www.google.org.uk -> google.org.uk -> google 

可选的:

 www.google.com -> google.com -> www.google images.google.com -> google.com -> images.google mail.yahoo.co.uk -> yahoo.co.uk -> mail.yahoo mail.yahoo.com -> yahoo.com -> mail.yahoo www.mail.yahoo.com -> yahoo.com -> mail.yahoo 

你不需要构build一个不断变化的正则expression式,因为如果你简单地看一下名字的后半部分,就可以正确匹配99%的域:

 (co|com|gov|net|org) 

如果是其中之一,则需要匹配3个点,否则2.简单。 现在,我的正则expression式与其他一些SO'ers是不匹配的,所以我发现实现这个最好的方法是使用一些代码,假设你已经剥离了path:

  my @d=split /\./,$domain; # split the domain part into an array $c=@d; # count how many parts $dest=$d[$c-2].'.'.$d[$c-1]; # use the last 2 parts if ($d[$c-2]=~m/(co|com|gov|net|org)/) { # is the second-last part one of these? $dest=$d[$c-3].'.'.$dest; # if so, add a third part }; print $dest; # show it 

按照你的问题来取名:

  my @d=split /\./,$domain; # split the domain part into an array $c=@d; # count how many parts if ($d[$c-2]=~m/(co|com|gov|net|org)/) { # is the second-last part one of these? $dest=$d[$c-3]; # if so, give the third last $dest=$d[$c-4].'.'.$dest if ($c>3); # optional bit } else { $dest=$d[$c-2]; # else the second last $dest=$d[$c-3].'.'.$dest if ($c>2); # optional bit }; print $dest; # show it 

我喜欢这种方法,因为它是免维护的。 除非你想validation它实际上是一个合法的域名,但这是没有意义的,因为你最有可能只使用它来处理日志文件,而一个无效的域名首先不会在那里find方法。

如果你想匹配“非官方”的子域,如bozo.za.net,或bozo.au.uk,bozo.msf.ru只需添加(za | au | msf)到正则expression式。

我很想看到有人使用正则expression式来完成这一切,我相信这是可能的。

/[^w{3}\.]([a-zA-Z0-9]([a-zA-Z0-9\-]{0,65}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}/gim

这个JavaScript正则expression式的使用忽略www和下面的点,同时保留域完好无损。 也适当匹配没有万维网和cc tld

如果没有使用顶级域名(TLD)列表来进行比较,就不可能像http://www.db.de/或http://bbc.co.uk/

但即使如此,由于像http://big.uk.com/或http://www.uk.com/这样的SLD,您在任何情况下都不会取得成功。;

如果你需要一个完整的列表,你可以使用公共后缀列表:

http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1

随意扩展我的function,只提取域名。 它不会使用正则expression式,速度很快:

http://www.programmierer-forum.de/domainnamen-ermitteln-t244185.htm#3471878

您需要列出可以删除哪些域前缀和后缀。 例如:

前缀:

  • www.

后缀:

  • .com
  • .co.in
  • .au.uk

所以,如果你只是一个string,而不是一个window.location你可以使用…

 String.prototype.toUrl = function(){ if(!this && 0 < this.length) { return undefined; } var original = this.toString(); var s = original; if(!original.toLowerCase().startsWith('http')) { s = 'http://' + original; } s = this.split('/'); var protocol = s[0]; var host = s[2]; var relativePath = ''; if(s.length > 3){ for(var i=3;i< s.length;i++) { relativePath += '/' + s[i]; } } s = host.split('.'); var domain = s[s.length-2] + '.' + s[s.length-1]; return { original: original, protocol: protocol, domain: domain, host: host, relativePath: relativePath, getParameter: function(param) { return this.getParameters()[param]; }, getParameters: function(){ var vars = [], hash; var hashes = this.original.slice(this.original.indexOf('?') + 1).split('&'); for (var i = 0; i < hashes.length; i++) { hash = hashes[i].split('='); vars.push(hash[0]); vars[hash[0]] = hash[1]; } return vars; } };}; 

如何使用。

 var str = "http://en.wikipedia.org/wiki/Knopf?q=1&t=2"; var url = str.toUrl; var host = url.host; var domain = url.domain; var original = url.original; var relativePath = url.relativePath; var paramQ = url.getParameter('q'); var paramT = url.getParamter('t'); 

为了某个特定的目的,我昨天做了这个快速的Python函数。 它从URL返回域。 这很快,不需要任何input文件列表的东西。 然而,我并不假装它在任何情况下都能正常工作,但它确实是我需要的一个简单文本挖掘脚本的工作。

输出如下所示:

http://www.google.co.uk => google.co.uk
http://24.media.tumblr.com/tumblr_m04s34rqh567ij78k_250.gif => tumblr.com

 def getDomain(url): parts = re.split("\/", url) match = re.match("([\w\-]+\.)*([\w\-]+\.\w{2,6}$)", parts[2]) if match != None: if re.search("\.uk", parts[2]): match = re.match("([\w\-]+\.)*([\w\-]+\.[\w\-]+\.\w{2,6}$)", parts[2]) return match.group(2) else: return '' 

似乎工作得很好。
但是,必须对其进行修改才能根据需要删除输出中的域扩展名。

使用这个(。)(。*?)(。)然后只提取前导点和终点。 很简单,对吧?

  1. 这怎么样

    =((?:(?:(?:http)s?:)?\/\/)?(?:(?:[a-zA-Z0-9]+)\.?)*(?:(?:[a-zA-Z0-9]+))\.[a-zA-Z0-9]{2,3}) (你可能想在模式结尾添加“\ /”

  2. 如果你的目标是把url作为一个参数去掉,你可以加上等号作为第一个字符,比如:

    =((:( 🙁 ?: HTTP)S:???)//)?(?:(?:[A-ZA-Z0-9] +))*(:?(?:[ A-ZA-Z0-9] +))。[A-ZA-Z0-9] {2,3} /)

    并用“/”replace

这个例子的目标是摆脱任何域名,而不pipe它出现的forms(即确保url参数不包含域名以避免xss攻击)

 #!/usr/bin/perl -w use strict; my $url = $ARGV[0]; if($url =~ /([^:]*:\/\/)?([^\/]*\.)*([^\/\.]+)\.[^\/]+/g) { print $3; } 
 /^(?:https?:\/\/)?(?:www\.)?([^\/]+)/i 

只是为了知识:

 'http://api.livreto.co/books'.replace(/^(https?:\/\/)([az]{3}[0-9]?\.)?(\w+)(\.[a-zA-Z]{2,3})(\.[a-zA-Z]{2,3})?.*$/, '$3$4$5'); # returns livreto.co