whois-0.8/0000755000175000017500000000000013467101255010620 5ustar hlehlewhois-0.8/README0000644000175000017500000000307213467101244011500 0ustar hlehlewhois ===== A Python module/library for retrieving WHOIS information of domains. By DDarko http://ddarko.org/ Features ============= * Python wrapper for Linux "whois" command * simple interface to access parsed WHOIS data for a given domain * able to extract data for all the popular TLDs (com, org, net, biz, info, pl, jp, uk, nz, ...) * query a WHOIS server directly instead of going through an intermediate web service like many others do * works with Python 2.4+ and Python 3.x * all dates as datetime objects * possibility to cache results Usage example ============= $pip install whois >>> import whois >>> domain = whois.query('google.com') >>> print(domain.__dict__) { 'expiration_date': datetime.datetime(2020, 9, 14, 0, 0), 'last_updated': datetime.datetime(2011, 7, 20, 0, 0), 'registrar': 'MARKMONITOR INC.', 'name': 'google.com', 'creation_date': datetime.datetime(1997, 9, 15, 0, 0) } >>> print(domain.name) google.com >>> print(domain.expiration_date) 2020-09-14 00:00:00 ccTLD & TLD support =================== ccTLD - at - be - br - co - co.jp - cz - de - eu - fr - it - jp - lv - nz - pl - ru - uk - us - mx - br - sh TLD - biz - com - info - me - name - net - org - io Issues ============= Raise an issue https://github.com/DannyCork/python-whois/issues/new Important: use the template below -Issue template- 1. What steps will reproduce the problem? 2. # python 3. What is the expected output? What do you see instead? 4. What version of the product are you using? On what operating system? 5. Please provide any additional information below. whois-0.8/whois/0000755000175000017500000000000013467101255011751 5ustar hlehlewhois-0.8/whois/_3_adjust.py0000644000175000017500000000670513466365301014211 0ustar hlehleimport re import sys import datetime PYTHON_VERSION = sys.version_info[0] class Domain: def __init__(self, data): self.name = data['domain_name'][0].strip().lower() self.registrar = data['registrar'][0].strip() self.creation_date = str_to_date(data['creation_date'][0]) self.expiration_date = str_to_date(data['expiration_date'][0]) self.last_updated = str_to_date(data['updated_date'][0]) #---------------------------------- # name_servers tmp = [] for x in data['name_servers']: if isinstance(x, str): tmp.append(x) else: for y in x: tmp.append(y) self.name_servers = set() for x in tmp: x = x.strip(' .') if x: if ' ' in x: x, _ = x.split(' ', 1) x = x.strip(' .') self.name_servers.add(x.lower()) #---------------------------------- # http://docs.python.org/library/datetime.html#strftime-strptime-behavior DATE_FORMATS = [ '%d-%b-%Y', # 02-jan-2000 '%d.%m.%Y', # 02.02.2000 '%d/%m/%Y', # 01/06/2011 '%Y-%m-%d', # 2000-01-02 '%Y.%m.%d', # 2000.01.02 '%Y/%m/%d', # 2005/05/30 '%Y.%m.%d %H:%M:%S', # 2002.09.19 13:00:00 '%Y%m%d %H:%M:%S', # 20110908 14:44:51 '%Y-%m-%d %H:%M:%S', # 2011-09-08 14:44:51 '%d.%m.%Y %H:%M:%S', # 19.09.2002 13:00:00 '%d-%b-%Y %H:%M:%S %Z', # 24-Jul-2009 13:20:03 UTC '%Y/%m/%d %H:%M:%S (%z)', # 2011/06/01 01:05:01 (+0900) '%Y/%m/%d %H:%M:%S', # 2011/06/01 01:05:01 '%a %b %d %H:%M:%S %Z %Y', # Tue Jun 21 23:59:59 GMT 2011 '%a %b %d %Y', # Tue Dec 12 2000 '%Y-%m-%dT%H:%M:%S', # 2007-01-26T19:10:31 '%Y-%m-%dT%H:%M:%SZ', # 2007-01-26T19:10:31Z '%Y-%m-%dt%H:%M:%S.%fz', # 2007-01-26t19:10:31.00z '%Y-%m-%dT%H:%M:%S%z', # 2011-03-30T19:36:27+0200 '%Y-%m-%dT%H:%M:%S.%f%z', # 2011-09-08T14:44:51.622265+03:00 '%Y-%m-%dt%H:%M:%S.%f', # 2011-09-08t14:44:51.622265 '%Y-%m-%dt%H:%M:%S', # 2007-01-26T19:10:31 '%Y-%m-%dt%H:%M:%SZ', # 2007-01-26T19:10:31Z '%Y-%m-%dt%H:%M:%S.%fz', # 2007-01-26t19:10:31.00z '%Y-%m-%dt%H:%M:%S%z', # 2011-03-30T19:36:27+0200 '%Y-%m-%dt%H:%M:%S.%f%z', # 2011-09-08T14:44:51.622265+03:00 '%Y%m%d', # 20110908 ] def str_to_date(s): s = s.strip().lower() if not s or s == 'not defined': return s = s.replace('(jst)', '(+0900)') s = re.sub('(\+[0-9]{2}):([0-9]{2})', '\\1\\2', s) s = re.sub('(\ #.*)', '', s) if PYTHON_VERSION < 3: return str_to_date_py2(s) for format in DATE_FORMATS: try: return datetime.datetime.strptime(s, format) except ValueError as e: pass raise ValueError("Unknown date format: '%s'" % s) def str_to_date_py2(s): tmp = re.findall('\+([0-9]{2})00', s) if tmp: tz = int(tmp[0]) else: z = 0 for format in DATE_FORMATS: try: return datetime.datetime.strptime(s, format) + datetime.timedelta(hours=tz) except ValueError as e: pass raise ValueError("Unknown date format: '%s'" % s) whois-0.8/whois/_2_parse.py0000644000175000017500000000270113466364711014024 0ustar hlehlefrom . import tld_regexpr import re TLD_RE = {} def get_tld_re(tld): if tld in TLD_RE: return TLD_RE[tld] v = getattr(tld_regexpr, tld) extend = v.get('extend') if extend: e = get_tld_re(extend) tmp = e.copy() tmp.update(v) else: tmp = v if 'extend' in tmp: del tmp['extend'] TLD_RE[tld] = dict((k, re.compile(v, re.IGNORECASE) if isinstance(v, str) else v) for k, v in tmp.items()) return TLD_RE[tld] [get_tld_re(tld) for tld in dir(tld_regexpr) if tld[0] != '_'] def do_parse(whois_str, tld): r = {} if whois_str.count('\n') < 5: s = whois_str.strip().lower() if 'extend' in tmp: del tmp['extend'] TLD_RE[tld] = dict((k, re.compile(v, re.IGNORECASE) if isinstance(v, str) else v) for k, v in tmp.items()) return TLD_RE[tld] [get_tld_re(tld) for tld in dir(tld_regexpr) if tld[0] != '_'] def do_parse(whois_str, tld): r = {} if whois_str.count('\n') < 5: s = whois_str.strip().lower() if s == 'not found': return if s.count('error'): return raise Exception(whois_str) sn = re.findall(r'Server Name:\s?(.+)', whois_str, re.IGNORECASE) if sn: whois_str = whois_str[whois_str.find('Domain Name:'):] for k, v in TLD_RE.get(tld, TLD_RE['com']).items(): if v is None: r[k] = [''] else: r[k] = v.findall(whois_str) or [''] return r whois-0.8/whois/__init__.py0000644000175000017500000000377013466365372014104 0ustar hlehle""" Python module/library for retrieving WHOIS information of domains. By DDarko.org ddarko@ddarko.org http://ddarko.org/ License MIT http://www.opensource.org/licenses/mit-license.php Usage example >>> import whois >>> domain = whois.query('google.com') >>> print(domain.__dict__) {'expiration_date': datetime.datetime(2020, 9, 14, 0, 0), 'last_updated': datetime.datetime(2011, 7, 20, 0, 0), 'registrar': 'MARKMONITOR INC.', 'name': 'google.com', 'creation_date': datetime.datetime(1997, 9, 15, 0, 0)} >>> print(domain.name) google.com >>> print(domain.expiration_date) 2020-09-14 00:00:00 """ from ._1_query import do_query from ._2_parse import do_parse, TLD_RE from ._3_adjust import Domain CACHE_FILE = None SLOW_DOWN = 0 def query(domain, force=0, cache_file=None, slow_down=0, ignore_returncode=0): """ force=1 Don't use cache. cache_file= Use file to store cache not only memory. slow_down=0 Time [s] it will wait after you query WHOIS database. This is useful when there is a limit to the number of requests at a time. """ assert isinstance(domain, str), Exception('`domain` - must be ') cache_file = cache_file or CACHE_FILE slow_down = slow_down or SLOW_DOWN domain = domain.lower().strip() d = domain.split('.') if d[0] == 'www': d = d[1:] if len(d) == 1: return None if domain.endswith('.co.jp'): tld = 'co_jp' elif domain.endswith('.xn--p1ai'): tld = 'ru_rf' else: tld = d[-1] if tld not in TLD_RE.keys(): raise Exception('Unknown TLD: %s\n(all known TLD: %s)' % (tld, list(TLD_RE.keys()))) while 1: pd = do_parse(do_query(d, force, cache_file, slow_down, ignore_returncode), tld) if (not pd or not pd['domain_name'][0]) and len(d) > 2: d = d[1:] else: break return Domain(pd) if pd['domain_name'][0] else None whois-0.8/whois/_1_query.py0000644000175000017500000000326113466364470014062 0ustar hlehleimport subprocess import time import sys import os PYTHON_VERSION = sys.version_info[0] CACHE = {} CACHE_MAX_AGE = 60*60*48 # 48h try: import json except: import simplejson as json def cache_load(cf): if not os.path.isfile(cf): return global CACHE f = open(cf, 'r') try: CACHE = json.load(f) except: pass f.close() def cache_save(cf): global CACHE f = open(cf, 'w') json.dump(CACHE, f) f.close() def do_query(dl, force=0, cache_file=None, slow_down=0, ignore_returncode=0): k = '.'.join(dl) if cache_file: cache_load(cache_file) if force or k not in CACHE or CACHE[k][0] < time.time() - CACHE_MAX_AGE: CACHE[k] = ( int(time.time()), _do_whois_query(dl, ignore_returncode), ) if cache_file: cache_save(cache_file) if slow_down: time.sleep(slow_down) return CACHE[k][1] def _do_whois_query(dl, ignore_returncode): """ Linux 'whois' command wrapper """ p = subprocess.Popen(['whois', '.'.join(dl)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) r = p.communicate()[0] r = r.decode() if PYTHON_VERSION == 3 else r if not ignore_returncode and p.returncode != 0 and p.returncode != 1: raise Exception(r) return r """ import socket def _do_whois_query(dl): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((('%s.whois-servers.net' % dl[-1], 43))) s.send(("%s\r\n" % '.'.join(dl)).encode()) response = [] while 1: t = s.recv(4096) response.append(t) if t == b'': break s.close() return b''.join(response).decode() """ whois-0.8/whois/tld_regexpr.py0000644000175000017500000001637413466365555014673 0ustar hlehlecom = { 'extend': None, 'domain_name': r'Domain Name:\s?(.+)', 'registrar': r'Registrar:\s?(.+)', 'registrant': None, 'creation_date': r'Creation Date:\s?(.+)', 'expiration_date': r'Expiration Date:\s?(.+)', 'updated_date': r'Updated Date:\s?(.+)$', 'name_servers': r'Name Server:\s*(.+)\s*', 'status': r'Status:\s?(.+)', 'emails': r'[\w.-]+@[\w.-]+\.[\w]{2,4}', } net = { 'extend': 'com', } org = { 'extend': 'com', 'creation_date': r'\nCreated On:\s?(.+)', 'expiration_date': r'\nRegistry Expiry Date:\s?(.+)', 'updated_date': r'\nLast Updated On:\s?(.+)', 'name_servers': r'Name Server:\s?(.+)\s*', } uk = { 'extend': 'com', 'registrant': r'Registrant:\n\s*(.+)', 'creation_date': r'Registered on:\s*(.+)', 'expiration_date': r'Renewal date:\s*(.+)', 'updated_date': r'Last updated:\s*(.+)', 'name_servers': r'Name Servers:\s*(.+)\s*', 'status': r'Registration status:\n\s*(.+)', } pl = { 'extend': 'uk', 'creation_date': r'\ncreated:\s*(.+)\n', 'updated_date': r'\nlast modified:\s*(.+)\n', 'name_servers': r'\nnameservers:\s*(.+)\n\s*(.+)\n', 'status': r'\nStatus:\n\s*(.+)', } ru = { 'extend': 'com', 'domain_name': r'\ndomain:\s*(.+)', 'creation_date': r'\ncreated:\s*(.+)', 'expiration_date': r'\npaid-till:\s*(.+)', 'name_servers': r'\nnserver:\s*(.+)', 'status': r'\nstate:\s*(.+)', } ru_rf = { 'extend': 'com', 'domain_name': r'\ndomain:\s*(.+)', 'creation_date': r'\ncreated:\s*(.+)', 'expiration_date': r'\npaid-till:\s*(.+)', 'name_servers': r'\nnserver:\s*(.+)', 'status': r'\nstate:\s*(.+)', } lv = { 'extend': 'ru', 'creation_date': r'Registered:\s*(.+)\n', 'updated_date': r'Changed:\s*(.+)\n', 'status': r'Status:\s?(.+)', } jp = { 'domain_name': r'\[Domain Name\]\s?(.+)', 'registrar': None, 'registrant': r'\[Registrant\]\s?(.+)', 'creation_date': r'\[Created on\]\s?(.+)', 'expiration_date': r'\[Expires on\]\s?(.+)', 'updated_date': r'\[Last Updated\]\s?(.+)', 'name_servers': r'\[Name Server\]\s*(.+)', 'status': r'\[Status\]\s?(.+)', 'emails': r'[\w.-]+@[\w.-]+\.[\w]{2,4}', } co_jp = { 'extend': 'jp', 'creation_date': r'\[Registered Date\]\s?(.+)', 'expiration_date': r'\[State\].+\((.+)\)', 'updated_date': r'\[Last Update\]\s?(.+)', } de = { 'extend': 'com', 'domain_name': r'\ndomain:\s*(.+)', 'updated_date': r'\nChanged:\s?(.+)', 'name_servers': r'Nserver:\s*(.+)', } at = { 'extend': 'com', 'domain_name': r'domain:\s?(.+)', 'updated_date': r'changed:\s?(.+)', 'name_servers': r'nserver:\s*(.+)', } eu = { 'extend': 'com', 'domain_name': r'\ndomain:\s*(.+)', 'registrar': r'Name:\s?(.+)', } biz = { 'extend': 'com', 'registrar': r'Sponsoring Registrar:\s?(.+)', 'registrant': r'Registrant Organization:\s?(.+)', 'creation_date': r'Domain Registration Date:\s?(.+)', 'expiration_date': r'Domain Expiration Date:\s?(.+)', 'updated_date': r'Domain Last Updated Date:\s?(.+)', 'status': None, } info = { 'extend': 'biz', 'creation_date': r'Created On:\s?(.+)', 'expiration_date': r'Expiration Date:\s?(.+)$', 'updated_date': r'Last Updated On:\s?(.+)$', 'status': r'Status:\s?(.+)', } name = { 'extend': 'com', 'status': r'Domain Status:\s?(.+)', } us = { 'extend': 'name', } co = { 'extend': 'biz', 'status': r'Status:\s?(.+)', } me = { 'extend': 'biz', 'creation_date': r'Domain Create Date:\s?(.+)', 'expiration_date': r'Domain Expiration Date:\s?(.+)', 'updated_date': r'Domain Last Updated Date:\s?(.+)', 'name_servers': r'Nameservers:\s?(.+)', 'status': r'Domain Status:\s?(.+)', } be = { 'extend': 'pl', 'domain_name': r'\nDomain:\s*(.+)', 'registrar': r'Company Name:\n?(.+)', 'creation_date': r'Registered:\s*(.+)\n', 'status': r'Status:\s?(.+)', } nz = { 'extend': None, 'domain_name': r'domain_name:\s?(.+)', 'registrar': r'registrar_name:\s?(.+)', 'registrant': r'registrant_contact_name:\s?(.+)', 'creation_date': r'domain_dateregistered:\s?(.+)', 'expiration_date': r'domain_datebilleduntil:\s?(.+)', 'updated_date': r'domain_datelastmodified:\s?(.+)', 'name_servers': r'ns_name_[0-9]{2}:\s?(.+)', 'status': r'query_status:\s?(.+)', 'emails': r'[\w.-]+@[\w.-]+\.[\w]{2,4}', } cz = { 'extend': 'com', 'domain_name': r'Domain:\s?(.+)', 'registrar': r'registrar:\s?(.+)', 'registrant': r'registrant:\s?(.+)', 'creation_date': r'registered:\s?(.+)', 'expiration_date': r'expire:\s?(.+)', 'updated_date': r'changed:\s?(.+)', 'name_servers': r'nserver:\s*(.+) ', } it = { 'extend': 'com', 'domain_name': r'Domain:\s?(.+)', 'registrar': r'Registrar:\s*Organization:\s*(.+)', 'registrant': r'Registrant:\s?Name:\s?(.+)', 'creation_date': r'Created:\s?(.+)', 'expiration_date': r'Expire Date:\s?(.+)', 'updated_date': r'Last Update:\s?(.+)', 'name_servers': r'Nameservers:\s?(.+)\s?(.+)\s?(.+)\s?(.+)', 'status': r'Status:\s?(.+)', } fr = { 'extend': 'com', 'domain_name': r'domain:\s?(.+)', 'registrar': r'registrar:\s*(.+)', 'registrant': r'contact:\s?(.+)', 'creation_date': r'created:\s?(.+)', 'expiration_date': None, 'updated_date': r'last-update:\s?(.+)', 'name_servers': r'nserver:\s*(.+)', 'status': r'status:\s?(.+)', } io = { 'extend': 'com', 'expiration_date': r'\nRegistry Expiry Date:\s?(.+)', } ca = { 'extend': 'com', 'domain_name': r'domain:\s?(.+)', 'registrar': r'registrar:\s*(.+)', 'registrant': r'contact:\s?(.+)', 'creation_date': r'created:\s?(.+)', 'expiration_date': None, 'updated_date': r'last-update:\s?(.+)', 'name_servers': r'nserver:\s*(.+)', 'status': r'status:\s?(.+)', } br = { 'extend': 'com', 'domain_name': r'domain:\s?(.+)', 'registrar': 'nic.br', 'registrant': None, 'owner': r'owner:\s?(.+)', 'creation_date': r'created:\s?(.+)', 'expiration_date': r'expires:\s?(.+)', 'updated_date': r'changed:\s?(.+)', 'name_servers': r'nserver:\s*(.+)', 'status': r'status:\s?(.+)', } mx = { 'domain_name': r'Domain Name:\s?(.+)', 'registrant': r'Registrant:\n\s*(.+)', 'registrar': r'Registrar:\s?(.+)', 'creation_date': r'Created On:\s?(.+)', 'expiration_date': r'Expiration Date:\s?(.+)', 'updated_date': r'Last Updated On:\s?(.+)', 'name_servers': r'\sDNS:\s*(.+)', } sh = { 'extend': 'com', 'expiration_date': r'\nRegistry Expiry Date:\s*(.+)', 'registrant': r'\nRegistrant Organization:\s?(.+)', 'status': r'\nDomain Status:\s?(.+)', } whois-0.8/setup.py0000644000175000017500000000206613467100542012334 0ustar hlehlefrom distutils.core import setup setup( name='whois', version='0.8', description='Python package for retrieving WHOIS information of domains.', long_description=open('README').read(), author='DannyCork', author_email='ddarko@ddarko.org', license='MIT http://www.opensource.org/licenses/mit-license.php', download_url='https://github.com/DannyCork/python-whois/releases/tag/0.8', url='https://github.com/DannyCork/python-whois/', platforms=['any'], packages=['whois'], keywords=['Python', 'WHOIS', 'TLD', 'domain', 'expiration', 'registrar'], classifiers=[ 'License :: OSI Approved :: MIT License', 'Intended Audience :: Developers', 'Environment :: Console', 'Programming Language :: Python', 'Programming Language :: Python :: 2.5', 'Programming Language :: Python :: 3.7', 'Topic :: Internet', 'Topic :: Software Development :: Libraries :: Python Modules', ], ) ''' test_suite='testsuite', entry_points=""" [console_scripts] cmd = package:main """, ''' whois-0.8/PKG-INFO0000644000175000017500000000605213467101255011720 0ustar hlehleMetadata-Version: 1.1 Name: whois Version: 0.8 Summary: Python package for retrieving WHOIS information of domains. Home-page: https://github.com/DannyCork/python-whois/ Author: DannyCork Author-email: ddarko@ddarko.org License: MIT http://www.opensource.org/licenses/mit-license.php Download-URL: https://github.com/DannyCork/python-whois/releases/tag/0.8 Description: whois ===== A Python module/library for retrieving WHOIS information of domains. By DDarko http://ddarko.org/ Features ============= * Python wrapper for Linux "whois" command * simple interface to access parsed WHOIS data for a given domain * able to extract data for all the popular TLDs (com, org, net, biz, info, pl, jp, uk, nz, ...) * query a WHOIS server directly instead of going through an intermediate web service like many others do * works with Python 2.4+ and Python 3.x * all dates as datetime objects * possibility to cache results Usage example ============= $pip install whois >>> import whois >>> domain = whois.query('google.com') >>> print(domain.__dict__) { 'expiration_date': datetime.datetime(2020, 9, 14, 0, 0), 'last_updated': datetime.datetime(2011, 7, 20, 0, 0), 'registrar': 'MARKMONITOR INC.', 'name': 'google.com', 'creation_date': datetime.datetime(1997, 9, 15, 0, 0) } >>> print(domain.name) google.com >>> print(domain.expiration_date) 2020-09-14 00:00:00 ccTLD & TLD support =================== ccTLD - at - be - br - co - co.jp - cz - de - eu - fr - it - jp - lv - nz - pl - ru - uk - us - mx - br - sh TLD - biz - com - info - me - name - net - org - io Issues ============= Raise an issue https://github.com/DannyCork/python-whois/issues/new Important: use the template below -Issue template- 1. What steps will reproduce the problem? 2. # python 3. What is the expected output? What do you see instead? 4. What version of the product are you using? On what operating system? 5. Please provide any additional information below. Keywords: Python,WHOIS,TLD,domain,expiration,registrar Platform: any Classifier: License :: OSI Approved :: MIT License Classifier: Intended Audience :: Developers Classifier: Environment :: Console Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.5 Classifier: Programming Language :: Python :: 3.7 Classifier: Topic :: Internet Classifier: Topic :: Software Development :: Libraries :: Python Modules