2 import socket as _socket
5 class Resolver (object):
6 """A simple reverse-DNS resolver.
8 Maintains a class-level cache of resolved IPs to avoid repeated
9 lookups on the same IP address.
11 Avoid hanging if we can't resolve a name.
14 >>> if hasattr(_socket, 'setdefaulttimeout'):
15 >>> socket.setdefaulttimeout(5) # set 5 second timeout
18 >>> r.resolve('198.41.0.4')
21 {'198.41.0.4': ('a.root-servers.net', [], ['198.41.0.4'])}
23 If you want to give shorter names to various DNS names, you can
24 add an entry to the class-level ``REGEXPS``. The entry should use
25 your name as the key, and a list of matching regexps as the value.
26 You need to enable this enhanced resolution using the ``smart``
29 >>> r.resolve('66.249.68.33')
30 'crawl-66-249-68-33.googlebot.com'
31 >>> r = Resolver(smart=True)
32 >>> r.resolve('66.249.68.34')
38 'feedburner': [_re.compile('.*rate-limited-proxy-.*.google.com.*')],
46 REGEXPS[bot] = [_re.compile('.*{}.*'.format(bot))]
48 def __init__(self, smart=False):
51 def resolve(self, ip):
54 self.IP[ip] = _socket.gethostbyaddr(ip)
55 except _socket.herror as e:
56 self.IP[ip] = (ip, [], [ip])
57 except _socket.gaierror as e:
58 self.IP[ip] = (ip, [], [ip])
61 self._smart_resolve(ip)
64 def _smart_resolve(self, ip):
67 for name,regexps in self.REGEXPS.items():
68 for regexp in regexps:
69 if regexp.match(self.IP[ip][0]):
70 self.IP[ip] = (name, x[1], x[2])
73 "Return a set of IP addresses used by a smart-resolved name."
75 for ip,values in self.IP.items():