8

How would you split a domain name that will return name and extension

2
  • This stackoverflow question may be useful: stackoverflow.com/questions/1066933/… Commented May 26, 2010 at 9:22
  • FWIW domains do not have "extensions". They have TLDs, or more generally a public suffix ("co.uk" is a public suffix under which you can register domain names, but is under the "uk" tld; all TLDs are public suffixes - modulo registry regulations on who can register domains there - but the contrary is not true). Commented Sep 22, 2023 at 22:43

9 Answers 9

23

Wow, there are a lot of bad answers here. You can only do this if you know what's on the public suffix list. If you are using split or a regex or something else, you're doing this wrong.

Luckily, this is python, and there's a library for this: https://pypi.python.org/pypi/tldextract

From their readme:

>>> import tldextract
>>> tldextract.extract('http://forums.news.cnn.com/')
ExtractResult(subdomain='forums.news', domain='cnn', suffix='com')

ExtractResult is a namedtuple. Makes it pretty easy.

The advantage of using a library like this is that they will keep up with the additions to the public suffix list so you don't have to.

Sign up to request clarification or add additional context in comments.

6 Comments

This would be nice if it worked reliably, but it doesn't work reliably AT ALL. Half the time it thinks the domain is part of the hostname and other times it thinks the suffix is the domain.
Can you provide some examples?
We have a domain called clmlb.loc where it decided that machines named: servername.clmlb.loc - the domain was loc while the clmlb was the servername and it dropped the servername entirely. I had an easier time just using the split method in this case. In any case I only wanted xxxx.xxx at the end anyway.
Well...um, .loc isn't a real suffix, is it? This only works on real domain names.
Great answer. I faced this issue too. Sometimes you get something like yahoo.com.sg. Using regex, yahoo will be considered the subdomain, com the rot and sg the extension which isn't right.
|
6

In general, it's not easy to work out where the user-registered bit ends and the registry bit begins. For example: a.com, b.co.uk, c.us, d.ca.us, e.uk.com, f.pvt.k12.wy.us...

The nice people at Mozilla have a project dedicated to listing domain suffixes under which the public can register domains: http://publicsuffix.org/

Comments

4

Depending on your application, be a little wary of simply taking the part following the last '.'. That works fine for .com, .net, .org, etc but will likely fall over for many County Code TLDs. E.g. bit.ly or google.co.uk.

(By which I mean 'bit.ly' probably prefer to be identified including the .ly TLD whereas google probably don't want to be identified with a spurious .co remainder. Whether that's important will obviously depend on what you're doing).

In those complicated cases ... well, you've got your work cut out I suspect!

A robust answer will probably depend on how you're gathering / storing your domains and what you really want back as the 'name'.

For example, if you've got a set of domain names, with no subdomain information, then you could do the opposite of what's suggested above and simply take the first part off:

>>> "stackoverflow.com".split('.')[0]
'stackoverflow'

1 Comment

so your saying that a hostname cannot be host.name ?
2

You mean internet domain name, like www.stackoverflow.com? If so, then just use:

>>> 'www.stackoverflow.com'.rsplit('.', 1)
['www.stackoverflow', 'com']

1 Comment

what if my FQDN is something like "madeup.name.madeup.domain.co.in"?
2

As other commenters have pointed out, there's no surefire way of doing this, short of having a dynamically updated list of TLDs and gTLDs. What works for google.com might not work for google.co.uk, or something.co.xx, or something.com.xx. Pretty much anything can be in a TLD or a gTLD and who knows what the future holds?

So there are two very different approaches:

  1. Use a library that has a regularly-updated list of TLDs and gTLDs, like tldextract.
  2. Use an algorithm that you know will fail on some edge-cases, but aim for as few as possible.

In my experience, the following satisfies #2 well, assuming you've already stripped off protocol and path:

def domain_from_hostname( hostname ):
    # Assume any TLD business will be dealt with in the last 7 bytes
    # This won't work for:
    # - Subdomains on supershort domains with short TLDs
    # - Domains with TLDs over 7 bytes long (".diamonds" anyone?) 
    if len(host) < 8:
        return host.strip( 'www.' )

    host_left = host[:-7].split('.')[-1]
    return u'%s%s' % ( host_left, host[-7:] )

Try it with some weirdness: a .com.au, .media, .in, .中信 etc.

Comments

0
domain = 'subdomain.domain.ext'
name, ext = domain.split('.')[-2:]

2 Comments

This only works for top-level US domains, in the form .com, .org, .ext etc. For other regions use the tldextract library as described in mlissner's answer below.
domain = 'google.com' name, ext = domain.split('.')[-2:] print(name) print(ext) # Here it print as name: "google" domain = "com/
0

If you always want to get the last part of a domain name, you can:

subdomain, _, domain= fqdn.rpartition('.')

Comments

0

I guess you will find urlparse module interesting: http://docs.python.org/library/urlparse.html

Comments

0

This is what I have come up with. Nothing fancy. It works for me. Although I do believe it gives weird feedback sometimes when there is characters like ?, +, so on. Still don't understand why.

scheme = 'https://www.msn.com/d/1234.php?=https://www.msn.com?+'
notfound = -1
https = scheme.rfind('http://')
com = scheme.rfind('.com')
if https != notfound:
    if com != notfound:
        domain = scheme[https:com+len('.com')]
        return scheme[https:com+len('.com')]

#Here we can grab the double suffix. This one has not been fully tested.

def getdoublesuffix(domain):
    '''
    :description: returns double dot TLD suffix endings or returns -1
    :function: 
    '''
    # ['www.domain.co.com'] to
    # ['www.domain', 'co', 'com']
    dots = domain.rsplit(sep='.', maxsplit=2)
# count dots by enumeration not string count! Only interested in enumeration count and
# not total dot count since it is split by '.' as a separator.
    for number, value in enumerate(dots, 0):
        value = value
        number = number
    if number is 2:
        # co.com
        result = '{0}.{1}'.format(dots[1], dots[2])
        return result
    else:
        #return that we do not have a domain ending in two dot notation.
        return -1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.